繁体   English   中英

根据另一个数据表更新一个数据表

[英]Update a data.table based on another data table

我想仅当值不是NA时,才根据新的data.table更新旧的data.table的列。

DT_old = data.table(x=rep(c("a","b","c")), y=c(1,3,6), v=1:3, l=c(1,1,1))
DT_old
   x y v l
1: a 1 1 1
2: b 3 2 1
3: c 6 3 1
DT_new = data.table(x=rep(c("b","c",'d')), y=c(9,6,10), v=c(2,NA,10), z=c(9,9,9))
DT_new
   x  y  v z
1: b  9  2 9
2: c  6  NA 9
3: d 10 10 9

我希望输出是

   x  y  v z
1: b  9  2 9
2: c  6  3 9
3: d 10 10 9
4: a 1 1 NA

目前,我正在合并两个data.table并遍历每一列,并替换新data.table中的NA

DT_merged <- merge(DT_new, DT_old, all=TRUE, by='x')
DT_merged
   x y.x v.x  z y.y v.y  l
1: a  NA  NA NA   1   1  1
2: b   9   2  9   3   2  1
3: c   6  NA  9   6   3  1
4: d  10  10  9  NA  NA NA
DT_merged[is.na(y.x), y.x := y.y]
DT_merged[is.na(v.x), v.x := v.y]
DT_merged = DT_merged[, list(y=y.x, v=v.x, z=z)

有没有更好的方法来执行以上操作?

这是我将如何处理的方法。 首先,我将使用二进制连接根据两个表的x列的唯一值组合来扩展DT_new

res <- setkey(DT_new, x)[unique(c(x, DT_old$x))]
res
#    x  y  v  z
# 1: b  9  2  9
# 2: c  6 NA  9
# 3: d 10 10  9
# 4: a NA NA NA

然后,我将使用另一个二进制连接通过引用更新res的两列

setkey(res, x)[DT_old, `:=`(y = i.y, v = i.v)]
res
#    x  y  v  z
# 1: a  1  1 NA
# 2: b  3  2  9
# 3: c  6  3  9
# 4: d 10 10  9

在注释部分之后,似乎您正在尝试按其自身的条件连接列。 没有简单的方法可以用R或任何语言AFAIK来做到这一点。 因此,您自己的解决方案本身可能是一个不错的选择。

不过,这里还有其他一些选择,主要取自我本人不久前问过的类似问题

使用两个ifelse陈述

setkey(res, x)[DT_old, `:=`(y = ifelse(is.na(y), i.y, y), 
                            v = ifelse(is.na(v), i.v, v))]

两个独立的条件联接

setkey(res, x) ; setkey(DT_old, x) ## old data set needs to be keyed too now
res[is.na(y), y := DT_old[.SD, y]]
res[is.na(v), v := DT_old[.SD, v]]

两者都会给您您所需要的。


PS

如果不需要警告,则需要正确定义相应的列类,例如DT_new v列应定义为v= c(2L, NA_integer_, 10L)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM