编辑编号 Infinity: Faq 1.12准确回答了您的问题:( FAQ 1.13也有用/相关,此处未粘贴)。
1.12 X[Y]和merge(X,Y)有什么区别?
X[Y] 是一个连接,使用 Y(或 Y 的键,如果有的话)作为索引来查找 X 的行。Y[X] 是一个连接,使用 X(或 X 的键,如果有的话)作为索引来查找 Y 的行。merge(X,Y)1 同时做这两种方式。X[Y] 和 Y[X] 的行数通常不同;而 merge(X,Y) 和 merge(Y,X) 返回的行数是相同的。但是这忽略了要点。大多数任务都需要在连接或合并后对数据执行某些操作。为什么要合并所有数据列,然后只使用其中的一小部分?
您可能会建议merge(X[,ColsNeeded1],Y[,ColsNeeded2])
,但这需要数据子集的副本,并且需要程序员确定需要哪些列。data.table 中的 X[Y,j] 为您一步完成所有这些. 当您编写时X[Y,sum(foo*bar)]
, data.table 会自动检查 j 表达式以查看它使用了哪些列。它只会对这些列进行子集化;其他的被忽略。仅为 j 使用的列创建内存,并且 Y 列在每个组的上下文中享受标准的 R 回收规则。假设 foo 在 X 中,而 bar 在 Y 中(以及 Y 中的 20 个其他列)。不是 X[Y,sum(foo*bar)]
比合并后跟一个子集更快地编程和运行吗?
旧答案对回答 OP 的问题没有任何帮助(来自 OP 的评论),保留在这里,因为我相信它确实如此)。
当您为j
liked[, 4]
或d[, value]
in提供值时data.table
, thej
被评估为expression
。从 data.table FAQ 1.1 on access DT[, 5]
(第一个常见问题解答):
因为,默认情况下,与 data.frame 不同,第二个参数是在 DT 范围内计算的表达式。5 评估为 5。
因此,在您的情况下,首先要了解的是:
d[, value] # produces a "vector"
# [1] 2 3 4 5 6
当查询是基本索引时,这没有什么不同,例如:i
d[3, value] # produces a vector of length 1
# [1] 4
但是,当is 本身是 a时,情况就不同了。引言(第 6 页):i
data.table
data.table
d[J(3)] # is equivalent to d[data.table(a = 3)]
在这里,您正在执行join
. 如果您只是这样做,d[J(3)]
那么您将获得与该联接对应的所有列。如果你这样做,
d[J(3), value] # which is equivalent to d[J(3), list(value)]
既然你说这个答案对回答你的问题没有任何帮助,我会指出我相信你的“改写”问题的答案在于:--->那么你只会得到那个专栏,但既然你正在表演连接,键列也将被输出(因为它是基于键列的两个表之间的连接)。
编辑:在您的第二次编辑之后,如果您的问题是为什么会这样?,那么我会不情愿地(或者说是无知地)回答,Matthew Dowle 的设计是为了区分 data.tablejoin-based-subset
和index-based-subset
ting 操作。
您的第二种语法相当于:
d[J(3)][, value] # is equivalent to:
dd <- d[J(3)]
dd[, value]
在哪里, in dd[, value]
,j
被评估为一个表达式,因此你得到一个向量。
要回答您的第三个修改问题:第三次,这是因为它是基于键列的两个 data.tables 之间的 JOIN 。如果我加入两个data.table
s,我期望一个data.table
从data.table
介绍开始,再次:
将 data.table 传递到 data.table 子集类似于基础 R 中的 A[B] 语法,其中 A 是矩阵,B 是 2 列矩阵。事实上,base R 中的 A[B] 语法启发了 data.table 包。