data.table 中的 eval 和 quote [英] eval and quote in 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
发生了什么事?我正在运行 R 2.15.0
和 data.table 1.8.9
.
What is going on? I'm running R 2.15.0
and data.table 1.8.9
.
推荐答案
更新(eddi):截至 版本 1.8.11 这已被修复和 .SD
在可以就地评估表达式的情况下不需要,例如在 OP 中.由于当前存在 .SD
会触发完整 .SD
的构造,因此在某些情况下这会导致速度更快.
UPDATE (eddi): As of version 1.8.11 this has been fixed and .SD
is not needed in cases where the expression can be evaluated in place, like in OP. Since currently presence of .SD
triggers construction of full .SD
, this will result in much faster speeds in some cases.
发生的情况是,对 eval()
的调用的处理方式与您在实现 [.data.table()
的代码中可能想象的不同.具体来说,[.data.table()
包含以符号 eval开头的
i
和 j
表达式的特殊评估分支代码>.当您在对 sum()
的调用中包装对 eval
的调用时,eval
不再是解析/替换表达式的第一个元素,并跳过特殊评估分支.
What's going on is that calls to eval()
are treated differently than you likely imagine in the code that implements [.data.table()
. Specifically, [.data.table()
contains special evaluation branches for i
and j
expressions that begin with the symbol eval
. When you wrap the call to eval
inside of a call to sum()
, eval
is no longer the first element of the parsed/substituted expression, and the special evaluation branch is skipped.
这是通过键入 getAnywhere("[.data.table")
显示的怪物函数中的一段代码,它特别允许调用 eval()
通过[.data.table()
的j
-argument:
Here is the bit of code in the monster function displayed by typing getAnywhere("[.data.table")
that makes a special allowance for calls to eval()
passed in via [.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 here),或明确地将 eval()
指向 .SD
,即保存您正在操作的任何 data.table 列的局部变量(这里是 d
).(有关 .SD
作用的更多解释,请参阅 这个答案).
As a workaround, either follow the example in data.table FAQ 1.6 (pdf here), or explicitly point eval()
towards .SD
, the local variable that holds columns of whatever data.table you are operating on (here d
). (For some more explanation of .SD
's role, see the first few paragraphs of this answer).
d[, sum(eval(quoted_a, envir=.SD))]
这篇关于data.table 中的 eval 和 quote的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!