比较两列中的每个元素并设置另一列

时间:2017-07-27 12:47:59

标签: r

我有一个数据框(来自文件的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] 

1 个答案:

答案 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

<强>更新

要确保您未将dep0-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.char‌​acter(i.id),allow.ca‌​rtesian=TRUE]