在R 2.15.0和data.table 1.8.9:
d = data.table(a = 1:5, value = 2:6, key = "a")
d[J(3), value]
# a value
# 3 4
d[J(3)][, value]
# 4
Run Code Online (Sandbox Code Playgroud)
我希望两者产生相同的输出(第二个),我相信它们应该.
为了清除这不是J语法问题,同样的期望适用于以下(与上述相同)表达式:
t = data.table(a = 3, key = "a")
d[t, value]
d[t][, value]
Run Code Online (Sandbox Code Playgroud)
我希望以上两个都返回完全相同的输出.
那么让我重新解释一下这个问题 - 为什么(data.table这样设计)关键列会自动打印出来d[t, value]?
更新(根据下面的答案和评论):感谢@Arun等人,我理解设计 - 为什么现在.究其原因,上面打印的关键是因为有一个隐藏的当前每次你做一个时间data.table通过合并X[Y]语法,这by是关键.它以这种方式设计的原因似乎如下 - 因为by必须在合并时执行操作,人们可以利用它而不是另外做另一个,by如果你要通过合并的键来做到这一点.
现在说,我认为这是一个语法设计缺陷.我阅读data.table语法的方式d[i, j, by = b]是
采取
d,应用i操作(是子集或合并或诸如此类),然后执行j表达"by"b
逐个打破这个阅读并介绍一个人必须具体思考的案例(我合并i,by只是合并的关键等).我认为这应该是data.table- 在data.table合并的一个特定情况下,当by等于键时,应该以另一种方式完成(例如通过内部检查by表达式是否实际上是合并的关键).
Aru*_*run 11
编辑号码无限:常见问题1.12 正好回答了你的问题:(也很有用/相关的是FAQ 1.13,这里没有粘贴).
1.12 X [Y]和合并(X,Y)有什么区别?
X [Y]是一个连接,使用Y(或Y的密钥,如果有的话)作为索引查找X的行.Y [X]是一个连接,使用X(或X的键,如果有的话)作为索引查找Y的行.merge(X,Y)1同时执行两种方式.X [Y]和Y [X]的行数通常为dier; 而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的评论),保留在这里,因为我相信它确实如此).
当您为jlike d[, 4]或d[, value]in 赋值时data.table,将j其评估为expression.从data.table FAQ 1.1访问DT[, 5](第一个常见问题解答):
因为,默认情况下,与data.frame不同,第二个参数是在DT范围内计算的表达式.5评估为5.
因此,首先要理解的是,在您的情况下:
d[, value] # produces a "vector"
# [1] 2 3 4 5 6
Run Code Online (Sandbox Code Playgroud)
当查询是基本索引时,这没有什么不同i:
d[3, value] # produces a vector of length 1
# [1] 4
Run Code Online (Sandbox Code Playgroud)
然而,当它本身是a 时,这是不同i的data.table.从data.table介绍(第6页):
d[J(3)] # is equivalent to d[data.table(a = 3)]
Run Code Online (Sandbox Code Playgroud)
在这里,你正在表演join.如果您这样做,d[J(3)]那么您将获得与该连接相对应的所有列.如果你这样做,
d[J(3), value] # which is equivalent to d[J(3), list(value)]
Run Code Online (Sandbox Code Playgroud)
既然你说这个答案没有回答你的问题,我会指出你的"改写"问题的答案在哪里,我相信:---> 然后你就会得到那个专栏,但是因为你在表演一个连接,键列也将被输出(因为它是基于键列的两个表之间的连接).
编辑:在你的第二次编辑之后,如果你的问题是为什么呢?那么我不情愿(或者说是无知)回答,马修道尔设计的是为了区分data.table join-based-subset和index-based-subsetting操作.
您的第二种语法相当于:
d[J(3)][, value] # is equivalent to:
dd <- d[J(3)]
dd[, value]
Run Code Online (Sandbox Code Playgroud)
其中,再次,在dd[, value],j被评估为的表达式,因此,你得到的载体.
回答第3个修改过的问题:第3次,这是因为它是基于键列的两个data.tables之间的JOIN.如果我加入两个data.table,我期待一个data.table
从data.table介绍,再次:
将data.table传递到data.table子集类似于基R中的A [B]语法,其中A是矩阵,B是2列矩阵.事实上,基础R中的A [B]语法启发了data.table包.
截至data.table 1.9.3,默认行为已更改,下面的示例产生相同的结果.要获得by-without-by结果,现在必须指定一个显式by=.EACHI:
d = data.table(a = 1:5, value = 2:6, key = "a")
d[J(3), value]
#[1] 4
d[J(3), value, by = .EACHI]
# a value
#1: 3 4
Run Code Online (Sandbox Code Playgroud)
这是一个稍微复杂的例子,说明了不同之处:
d = data.table(a = 1:2, b = 1:6, key = 'a')
# a b
#1: 1 1
#2: 1 3
#3: 1 5
#4: 2 2
#5: 2 4
#6: 2 6
# normal join
d[J(c(1,2)), sum(b)]
#[1] 21
# join with a by-without-by, or by-each-i
d[J(c(1,2)), sum(b), by = .EACHI]
# a V1
#1: 1 9
#2: 2 12
# and a more complicated example:
d[J(c(1,2,1)), sum(b), by = .EACHI]
# a V1
#1: 1 9
#2: 2 12
#3: 1 9
Run Code Online (Sandbox Code Playgroud)