20

我在这里想念什么?

d = data.table(a = 1:5)

d[, a]                   # 1 2 3 4 5
d[, sum(a)]              # 15

d[, eval(quote(a))]      # 1 2 3 4 5
d[, sum(eval(quote(a)))] # 15

quoted_a = quote(a)
d[, eval(quoted_a)]      # 1 2 3 4 5
d[, sum(eval(quoted_a))] # Error in eval(expr, envir, enclos) : object 'a' not found

到底是怎么回事?我正在跑步R 2.15.0data.table 1.8.9

4

1 回答 1

22

更新(eddi):版本 1.8.11开始,这已得到修复,并且.SD在可以就地评估表达式的情况下不需要,例如在 OP 中。由于当前存在.SD触发器构建 full .SD,因此在某些情况下这将导致更快的速度。


发生的情况是调用eval()的处理方式与您在实现[.data.table(). 具体来说,包含以符号 开头的和表达式的[.data.table()特殊评估分支。当您将调用包装到调用内部时,不再是已解析/替换表达式的第一个元素,并且会跳过特殊评估分支。ijevalevalsum()eval

这是通过键入显示的怪物函数getAnywhere("[.data.table")中的一段代码,它特别允许eval()通过[.data.table()'s j-argument 传入的调用:

jsub = substitute(j)
    ...
    # Skipping some lines
    ...
jsubl = as.list.default(jsub)
if (identical(jsubl[[1L]], quote(eval))) {  # The test for eval 'on the outside' 
    jsub = eval(jsubl[[2L]], parent.frame(), parent.frame())
    if (is.expression(jsub)) 
        jsub = jsub[[1L]]
}

作为一种解决方法,要么遵循 data.table FAQ 1.6(此处为 pdf)中的示例,要么明确指向eval()保存.SD您正在操作的任何 data.table 列的局部变量(此处d)。(有关 ' 角色的更多解释,请参阅此答案.SD的前几段)。

d[, sum(eval(quoted_a, envir=.SD))]
于 2013-04-09T22:53:59.257 回答