data.table 中的 eval 和 quote [英] eval and quote in data.table

查看:12
本文介绍了data.table 中的 eval 和 quote的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里错过了什么?

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.

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() 包含以符号 evalij 表达式的特殊评估分支代码>.当您在对 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆