eval和data.table中的引用

edd*_*ddi 18 r data.table

我在这里错过了什么?

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
Run Code Online (Sandbox Code Playgroud)

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

Jos*_*ien 20

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


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

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

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]]
}
Run Code Online (Sandbox Code Playgroud)

作为一种变通方法,要么效仿在data.table常见问题1.6(PDF这里),或明确指出eval().SD,持有任何data.table你在(这里工作的列局部变量d).(有关.SD角色的更多解释,请参阅本答案的前几段).

d[, sum(eval(quoted_a, envir=.SD))]
Run Code Online (Sandbox Code Playgroud)

  • @eddi - 在不使用`[.data.table`中的特殊情况时使用`eval`的正确环境([this answer] n(http://stackoverflow.com/a/11874464/1385941)可能有用(使用`sum(eval(quoted_a,.SD))`将起作用....) (3认同)
  • @Arun - 你很有意义.**data.table**的力量来自于其用户必须构建一个关于其"真正"发生的魔法的完整附加模型的成本.我自己仍然处于学习曲线的陡峭部分;) (3认同)
  • 尽管如此,我还是认为`data.table`不应该在命令行中做任何破坏嵌套函数预期行为的事情.如果`regular_matrix [,sum(eval(quoted_a))]`"工作",则`data.table`未能这样做应被视为错误. (3认同)
  • @Arun - 哦,我明白了.我想你只需要了解`.SD`在评估所有`i`和`j`表达式中的核心作用.[我的回答](http://stackoverflow.com/questions/15667984/can-sd-be-viewed-from-a-browser-within-data-table/15668311#15668311)中的开场笔记应该让它变得漂亮清楚为什么`.SD`是你想要的环境.我希望你不能通过调用`parent.frame()`找到它,因为`[.data.table`回避/重新路由一些R的典型范围规则. (2认同)