在data.table中按引用合并所有列

时间:2017-07-11 20:04:24

标签: r data.table

大家下午好,

我想通过引用将两个data.table合并在一起,而不必记下我想要合并的所有变量。这是一个了解我需求的简单示例:

> set.seed(20170711)
> (a <- data.table(v_key=seq(1, 5), key="v_key"))
   v_key
1:     1
2:     2
3:     3
4:     4
5:     5

> a_backup <- copy(a)

> (b <- data.table(v_key=seq(1, 5), v1=runif(5), v2=runif(5), v3=runif(5),     key="v_key"))
   v_key          v1        v2          v3
1:     1 0.141804303 0.1311052 0.354798849
2:     2 0.425955903 0.3635612 0.950234261
3:     3 0.001070379 0.4615936 0.359660693
4:     4 0.453054854 0.5768500 0.008470552
5:     5 0.951767837 0.1649903 0.565894298

我想通过引用将b的每一列复制到a,而不指定列名。

我可以执行以下操作,但这样会无缘无故地复制对象,从而降低程序的性能并增加所需的RAM:

> (a  <- a[b])
   v_key          v1        v2          v3
1:     1 0.141804303 0.1311052 0.354798849
2:     2 0.425955903 0.3635612 0.950234261
3:     3 0.001070379 0.4615936 0.359660693
4:     4 0.453054854 0.5768500 0.008470552
5:     5 0.951767837 0.1649903 0.565894298

另一个选项(没有无用的副本)将指定b的每一列的名称,从而产生以下结果:

> a <- copy(a_backup)
> a[b, `:=`(
+   v1=v1,
+   v2=v2,
+   v3=v3
+ )][]
   v_key          v1        v2          v3
1:     1 0.141804303 0.1311052 0.354798849
2:     2 0.425955903 0.3635612 0.950234261
3:     3 0.001070379 0.4615936 0.359660693
4:     4 0.453054854 0.5768500 0.008470552
5:     5 0.951767837 0.1649903 0.565894298

简而言之,我希望能够提高第二个示例的效率(没有无用的副本),而无需在b中指定每个列名。

我想我可以找到一种使用colnames()get()函数组合的方法,但我想知道是否有更简洁的方法来实现它,语法非常重要我

感谢大家的贡献!

JPL

2 个答案:

答案 0 :(得分:3)

正如您所写,colnamesmget的组合可以帮助您。

考虑一下:

# retrieve the column names from b - without the key ('v_key')
thecols = setdiff(colnames(b), key(b))

# assign them to a
a[b, (thecols) := mget(thecols)]

这不是太糟糕了,是吗?

此外,我不认为目前使用data.table实现了另一种语法。但我很高兴被证明是错误的:)

答案 1 :(得分:0)

回顾related question here作为一个例子,在这种情况下我总是喜欢Reduce

# provide list of DTs to be merged
arbitrary.dts <- list(...)

a <- Reduce(function(x, y) merge(x, y, all=T, 
    by=c("v_key")), arbitrary.dts, accumulate=F)

只有一个想法(我总是喜欢从基本功能开始)。我确信现在有一个更加流畅的data.table答案。