微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

R:与第二个表合并更新表的高效方法来自相同列名的值填充NAs

总结:我想通过共享id键将两个表合并为all = true(全外连接),而不是具有相同名称的列被设置为var1.x var2.y等,它们被合并为单列其中左表中的缺失(NA)值由右侧表格中的值(除了合并的标准行为外,也就是附加具有不同名称的列和列的行)填充.

细节:

我想根据共享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的修改.

原文地址:https://www.jb51.cc/mssql/79165.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐