Max*_*den 3 replace r data.table
由于我对上一个问题的执行和解释很糟糕,因此我将重新开始,并将尝试将问题简化为简短而笼统的问题。
我有两个数据框(请参见下面的示例)。每个数据集包含相同数量的列。
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)
Run Code Online (Sandbox Code Playgroud)
我们的目标是从一个地方最旧的ID MATCHINGS为INVOLVED通过匹配Track1来Track4和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
Run Code Online (Sandbox Code Playgroud)
我尝试使用此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 }
}
Run Code Online (Sandbox Code Playgroud)
更新
更新了显示需要的示例数据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参数还可以将下一个观察值与new(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")]]]
Run Code Online (Sandbox Code Playgroud)
而已。
这是一个data.table-ish的开始。这仅使用轨道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
Run Code Online (Sandbox Code Playgroud)
有趣的问题!如果这样没问题,请更改示例数据以将轨道1更改为3。或者也许可以从此处获取。