由于我对 previous question 的糟糕执行和解释,我将重新开始并尝试尽可能简短和概括地提出问题。
我有两个数据框(见下面的例子)。每个数据集包含相同数量的列。
tc <- textConnection('
ID Track1 Track2 Track3 Track4 Time Loc
4 15 "" "" 50 40 1
5 17 115 109 55 50 1
6 17 115 109 55 60 1
7 13 195 150 60 70 1
8 13 195 150 60 80 1
9 "" "" 181 70 90 2 #From this row, example data added
10 "" "" 182 70 92 2
11 429 31 "" 80 95 3
12 480 31 12 80 96 3
13 118 "" "" 90 100 4
14 120 16 213 90 101 4
')
MATCHINGS <- read.table(tc, header=TRUE)
tc <- textConnection('
ID Track1 Track2 Track3 Track4 Time Loc
"" 15 "" "" 50 40 1
"" 17 "" 109 55 50 1
"" 17 432 109 55 65 1
"" 17 115 109 55 59 1
"" 13 195 150 60 68 1
"" 13 195 150 60 62 1
"" 10 5 1 10 61 3
"" 13 195 150 60 72 1
"" 40 "" 181 70 82 2 #From this row, example data added
"" "" "" 182 70 85 2
"" 429 "" "" 80 90 3
"" "" 31 12 80 92 3
"" "" "" "" 90 95 4
"" 118 16 213 90 96 4
')
INVOLVED <- read.table(tc, header=TRUE)
目标是通过将
MATCHINGS
与 INVOLVED
和 Track1
进行匹配,将 Track4
中最近的 ID 放入 Loc
中。一个额外的条件是匹配的 Time
条目的 INVOLVED
不能高于 Time
条目的 MATCHING
。此外,Track1
上的匹配是最优选的,Track4
上的匹配是最不优选的。然而,只有 Track4
始终可用(所有其他 Track
列可以为空)。因此,预期的结果是:ID Track1 Track2 Track3 Track4 Time Loc
4 15 "" "" 50 40 1
5 17 "" 109 55 50 1
"" 17 432 109 55 65 1
6 17 115 109 55 59 1
7 13 195 150 60 68 1
7 13 195 150 60 62 1
"" 10 5 1 10 61 3
8 13 195 150 60 72 1
9 40 "" 181 70 82 2 #From this row, example data added
10 "" "" 182 70 85 2
11 429 "" "" 80 90 3
12 "" 31 12 80 92 3
13 "" "" "" 90 95 4
13 118 16 213 90 96 4
我尝试使用
data.table
包进行此操作,但未能有效执行此操作。是否有可能摆脱矢量扫描并有效地遍历数据而不循环?dat <- data.table(MATCHINGS)
for(i in 1:nrow(INVOLVED)){
row <- INVOLVED[i,]
match <- dat[Time>=row$Time][Loc==row$Loc][Track4==row$Track4][Track4!=""][order(Time)][1]
if(!is.na(match$ID)){ INVOLVED$ID[i]<-match$ID }
match <- dat[Time>=row$Time][Loc==row$Loc][Track3==row$Track3][Track3!=""][order(Time)][1]
if(!is.na(match$ID)){ INVOLVED$ID[i]<-match$ID }
match <- dat[Time>=row$Time][Loc==row$Loc][Track2==row$Track2][Track2!=""][order(Time)][1]
if(!is.na(match$ID)){ INVOLVED$ID[i]<-match$ID }
match <- dat[Time>=row$Time][Loc==row$Loc][Track1==row$Track1][Track1!=""][order(Time)][1]
if(!is.na(match$ID)){ INVOLVED$ID[i]<-match$ID }
}
更新
更新了显示需要
Track 1 to 3
的示例数据。如图所示,Track1
最重要,Track4
最不重要。即使 Track1 to 3
匹配 MATCHINGS x
并且 Track4
匹配 MATCHINGS y
, ID
的 y
也应该分配给那个 INVOLVED row
。所以:Track3
匹配覆盖 Track4
匹配,Track2
匹配覆盖 Track3
匹配,Track1
匹配覆盖 Track2
匹配。 最佳答案
随着 roll 参数还能够将下一个观察结果与新的 ( v1.9.6+
) on=
参数一起向后滚动,我们可以更直接地做到这一点:
require(data.table)
setDT(MATCHINGS)
setDT(INVOLVED)
INVOLVED[ , ID := MATCHINGS[INVOLVED, ID, roll=-Inf,
mult="first", on=c("Loc", "Track4", "Time")]]]
就是这样。
这是一个
data.table
-ish 开始。这仅使用 Track 4(而不是 1 到 3),但它似乎仍会产生请求的输出。M = as.data.table(MATCHINGS)
I = as.data.table(INVOLVED)
M[,Time:=-Time]
I[,Time:=-Time]
setkey(M,Loc,Track4,Time)
I[,ID:={i=list(Loc,Track4,Time);M[i,ID,roll=TRUE,mult="first"]}][,Time:=-Time]
ID Track1 Track2 Track3 Track4 Time Loc
1: 1 NA 105 NA 35 1 1
2: 1 NA NA NA 35 2 1
3: 1 26 105 NA 35 3 1
4: 2 NA NA NA 40 20 1
5: 2 134 1 6 40 20 1
6: 3 13 109 NA 45 30 1
7: 4 15 NA NA 50 40 1
8: 5 17 NA 109 55 50 1
9: NA 17 432 109 55 65 1
10: 6 17 115 109 55 59 1
11: 7 13 195 150 60 68 1
12: 7 13 195 150 60 62 1
13: NA 10 5 1 10 61 3
14: 8 13 195 150 60 72 1
有趣的问题!如果这看起来没问题,请将示例数据更改为需要轨道 1 到 3。或者您可以从这里获取它。
关于r - 组合 data.table 中的一组条件以使用二分搜索提取值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12723182/