27

我有两个data.tables,X(3m 行,约 500 列)和 Y(100 行,两列)。

set.seed(1)
X <- data.table( a=letters, b=letters, c=letters, g=sample(c(1:5,7),length(letters),replace=TRUE), key="g" )
Y <- data.table( z=runif(6), g=1:6, key="g" )

我想在 X 上进行左外连接,这Y[X]要归功于:

为什么 data.tables 的 X[Y] 连接不允许完全外连接或左连接?

但我想在X 复制X的情况下添加新列(因为它很大)。

显然,类似X <- Y[X]作品的东西,但除非data.table比我认为的要聪明得多(而且我认为它有很多狡猾!),我相信这复制了整个X.

X[ , z:= Y[X,z]$z ]有效,但很笨拙,不能很好地扩展到一列以上。

如何以有效的方式(在副本和程序员时间方面)将合并的结果存储回保留的 data.table 中?

4

2 回答 2

32

这很容易做到:

X[Y, z := i.z]

Y[X]它之所以有效,是因为和之间的唯一区别X[Y]是,当某些元素不在时Y,在这种情况下,您可能想要z成为NA,上面的分配正是这样做的。

它也适用于许多变量:

X[Y, `:=`(z1 = i.z1, z2 = i.z2, ...)]

由于您需要 operation Y[X],因此您可以添加参数nomatch=0(如@mnel 指出的那样),以免 X 不包含来自 Y 的键值的那些获得 NA。即:

X[Y, z := i.z, nomatch=0]

来自data.table 的 NEWS

    **********************************************
    **                                          **
    **   CHANGES IN DATA.TABLE VERSION 1.7.10   **
    **                                          **
    **********************************************

新功能

o   The prefix i. can now be used in j to refer to join inherited
    columns of i that are otherwise masked by columns in x with
    the same name.
于 2013-10-23T22:12:31.587 回答
9

作为上述答案的补充,您还可以执行 ( v1.9.6+):

require(data.table) # v1.9.6+
X[Y, (colNames) := mget(paste0("i.", colNames))]

wherecolNames是列出您想要的列的字符向量Y。这使您可以在添加许多列的情况下有效地选择要添加的列(colNames从 的子集定义)。names(Y)

此外,您可以将其与新on=参数 (from v1.9.6+) 组合为:

# ad-hoc joins using 'on=' instead of setting keys
require(data.table) # v1.9.6+
X[Y, (colNames) := mget(paste0("i.", colNames)), on = "g"]

将这里的策略归功于 akrun (colNames) := mget(colNames)更新 R 中的数据框行

于 2015-11-17T21:01:02.750 回答