我有一个数据框(来自文件的fread),有两列(dep和label)。我想根据匹配设置另一个具有id值的列(标记)。如果'dep'条目与'lablel'条目匹配,则标记匹配'label'的'id'。如果不匹配,则标记获取其自己的“id”的值。目前,我已经解决了循环问题,但我知道在R细节中应该有一个巧妙的方法。
trace <- data.table(id=seq(1:7),dep=c(-1,45,40,47,0,45,43),
label=c(99,40,43,45,47,42,48), mark=rep("",7))
id dep label mark
1: 1 -1 99 1
2: 2 45 40 2
3: 3 40 43 2
4: 4 47 45 4
5: 5 0 47 5
6: 6 45 42 4
7: 7 43 48 3
我知道循环在r中很慢,只是为了举例说明以下天真for / while适用于小尺寸但我的数据集很大。
trace$mark <- trace$id
for (i in 1:length(trace$id)){
val <- trace$dep[i]
j <- 1
while(j<=i && val !=-1 && val!=0){ // don't compare if val is -1/0
if(val==trace$label[j]){
trace$mark[i] <- trace$id[j]
}
j <-j +1
}
}
我也尝试过使用以下方法,但只有在匹配时才有效。
match <- which(trace$dep %in% trace$label)
match_to <- which(trace$label %in% trace$dep)
trace$mark[match] <- trace$mark[match_to]
答案 0 :(得分:1)
此解决方案可能有所帮助:
trace[trace[,.(id,dep=label)],mark:=as.character(i.id),on="dep"]
trace[mark=="",mark:=as.character(id)]
# id dep label mark
# 1: 1 -1 99 1
# 2: 2 45 40 4
# 3: 3 -1 43 3
# 4: 4 47 45 5
# 5: 5 -1 47 5
# 6: 6 45 42 4
# 7: 7 43 48 3
<强>更新强>
要确保您未将dep
与0
或-1
值匹配,您只需添加另一行。
trace[dep %in% c(0,-1), mark:= as.character(id)]
或强> 试试这个:
trace[trace[!dep %in% c(0,-1),.(id,dep=label)],mark:=as.character(i.id),on="dep"]
trace[mark=="",mark:=as.character(id)]
有效的解决方案
trace[trace[,.(id,dep=label)],on=.(id<=id,dep),mark:=as.character(i.id),allow.cartesian=TRUE]