在data.table中的eval和quote [英] eval and quote in data.table
问题描述
我在这里缺少什么?
d = data.table(a = 1:5)
b $ bd [,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))]#eval中的错误(expr,envir,enclos):object'a'not found
发生了什么事?我正在运行
R 2.15.0
和data.table 1.8.9
。解决方案UPDATE(eddi):截至版本1.8.11 已修复,
.SD
在表达式可以就地评估的情况下不需要,如在OP中。由于当前存在.SD
触发构建完整.SD
,在某些情况下会导致更快的速度。
所做的是调用
eval()
处理不同于你可能想象在实现[。data.table()
的代码。具体地,[。data.table()
包含i
和j
以符号eval
开头的表达式。当你调用sum()
,eval / code>不再是解析/替换表达式的第一个元素,并跳过特殊的求值分支。
这里是代码的位通过键入
getAnywhere([。data.table)
显示的怪物函数对调用eval()
通过[。data.table()
'j
- 提交:jsub = substitute(j)
...
跳过某些行
...
jsubl = as.list.default(jsub)
if(identical(jsubl [[1L]],quote(eval))){#在外部测试eval'
jsub = eval
if(is.expression(jsub))
jsub = jsub [[1L]]
} $ jsub [[2L]],parent.frame作为一种解决方法,请按照data.table中的示例常见问题1.6( //datatable.r-forge.r-project.org/datatable-faq.pdf\">此处),或明确指向eval()
朝.SD
是保存您正在操作的任何data.table列的局部变量(这里d
)。 (有关.SD
的更多解释,请参阅 this answer )。code> d [,sum(eval(quoted_a,envir = .SD))]
What am I missing here?
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
What is going on? I'm running
R 2.15.0
anddata.table 1.8.9
.解决方案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.
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 fori
andj
expressions that begin with the symboleval
. When you wrap the call toeval
inside of a call tosum()
,eval
is no longer the first element of the parsed/substituted expression, and the special evaluation branch is skipped.Here is the bit of code in the monster function displayed by typing
getAnywhere("[.data.table")
that makes a special allowance for calls toeval()
passed in via[.data.table()
'sj
-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]] }
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 (hered
). (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屋!