细节:
我想根据共享id键列将update table1与table2合并,以便:
1)如果table1和table2具有相同名称(id除外)的列,如果table1中的值为NA,则table1中的值如果存在并被table2中的值替换,则将其替换.
2)如果table2具有table1没有的列(不同的名称),则它们将被合并(按id).
3)如果table1具有与table2不匹配的id,则表2中不同名称列的值为NA
4)如果table2具有与table1不匹配的id,则作为新行添加,并且table1中不同列名的值为NA.
3& 4与标准合并与all = TRUE相同.
我担心我已经考虑了这个问题,因为我找不到一个直接的方式来做这个合并或联接,不涉及在每一列上创建ifelse检查.真正的数据有〜1000列,所以要非常长的解决方案来进行ifelse查找.
可重现的简化示例:
table1 <- data.table(id =c("id1","id2","id3","id4","id5","id6"),var1=c(1,2,3,4,5,6),var2=c("a","b",NA,"d","f"),var3=c(NA,12,13,14,15,16)); table2 <- data.table(id =c("id1","id8"),8),var2=c(NA,"c","e","h"),var4=c("foo","bar","oof","rab","sna")); desired <- data.table(id=c("id1","id6",6,"f",16,NA),"sna")); table1; id var1 var2 var3 1: id1 1 a NA 2: id2 2 b 12 3: id3 3 NA 13 4: id4 4 d 14 5: id5 5 e 15 6: id6 6 f 16 table2; id var1 var2 var4 1: id1 1 a foo 2: id2 2 b bar 3: id3 NA c oof 4: id4 4 d rab 5: id5 5 e NA 6: id8 8 h sna desired id var1 var2 var3 var4 1: id1 1 a NA foo 2: id2 2 b 12 bar 3: id3 3 c 13 oof 4: id4 4 d 14 rab 5: id5 5 e 15 NA 6: id6 6 f 16 NA 7: id8 8 h NA sna
所需输出的说明:
>对于列var1,table1具有所有值,因此它被单独存在,并且table2中id3的NA被忽略(注意,这不包括下面描述的不同ID的行合并).
>对于列var2,表缺少由id3索引的值,所以它从table2更新(注意,这不包括下面描述的不同id的行合并).
>对于列var3,表2中没有匹配的列,因此保持原样.
>对于列var4,table1中没有列var4,所以它通过id键变量从table2合并.
>对于table1中id6的行,table2中没有匹配的id6,因此只有在table2中的列var4的值在行ID6的所需输出中为NA.
>对于表2中的id8的行,table1中没有匹配的id8,因此只有在table1中的列var3的值在行id8的所需输出中为NA.
当然有一个直接的方法来做到这一点与data.table?鉴于实际数据的大小,高效的解决方案是特别受欢迎的. datamerge包显然是这样做的,但它不在CRAN上,我不能让它在zip上工作在R3.2.3上.有另一个包装加强了这项任务吗?还有许多其他线程专注于为已知名称的一列或两列进行解决,但对于大量的列,它们似乎不实用.
解决方法
com.cols = setdiff(intersect(names(table1),names(table2)),"id") com.cols.x = paste0(com.cols,".x") com.cols.y = paste0(com.cols,".y") # create combined table DT = setkey(merge(table1,table2,by="id",all=TRUE),NULL) # edit common columns where NAs are present for (j in seq_along(com.cols)) DT[is.na(get(com.cols.x[j])),(com.cols.x[j]) := get(com.cols.y[j])] # remove unneeded columns DT[,(com.cols.y) := NULL] # rename kept columns setnames(DT,com.cols.x,com.cols) identical(DT,desired) # TRUE
创建和使用所有这些列名称向量是相当凌乱的.
关于原来的问题…
这是另一种方式(没有从表2导入新行,如原始帖子):
com.cols = setdiff(intersect(names(table1),"id") i.com.cols = paste0("i.",com.cols) new.cols = c(i.com.cols,setdiff(names(table2),c("id",com.cols))) # grab columns from table2 table1[table2,(new.cols) := mget(new.cols),on="id"] # edit common columns where NAs are present for (j in seq_along(com.cols)) table1[is.na(get(com.cols[j])),(com.cols[j]) := get(i.com.cols[j])] # remove unneeded columns table1[,(i.com.cols) := NULL]
这样,所有步骤都是通过引用对table1的修改.