使用j环境中的函数进行列选择

Ryo*_*ogi 9 r data.table

请考虑以下列中的列选择data.table:

library(data.table) # using 1.8.7 from r-forge
dt <- data.table(a = 1:5, b = i <- rnorm(5), c = pnorm(i))
dt[, list(a,b)]  #ok
Run Code Online (Sandbox Code Playgroud)

为了在具有许多和可变列的某些计算中简化我的代码,我想list(a,b)用函数替换.这是第一次尝试:

.ab <- function()  quote(list(a, b))
dt[, eval(.ab())] #ok - same as above
Run Code Online (Sandbox Code Playgroud)

理想情况下,我想摆脱eval()来自[.data.table呼叫,它限制在定义.ab的同时避免将数据表,而dt该函数.ab.

.eab <- function()  eval(quote(list(a, b)))
dt[, .eab()] 
# Error in eval(expr, envir, enclos) : object 'b' not found
Run Code Online (Sandbox Code Playgroud)

发生了什么?怎么解决这个问题?

我怀疑是什么让我感到愤怒的是R的词汇范围以及正确的评估list(a,b)依赖于它在数据表的J环境中dt.唉,我不知道如何获取对正确环境的引用,并将其用作envirenclos参数dt.

# .eab <- function()  eval(quote(list(a, b)), envir = ?, enclos = ?)
Run Code Online (Sandbox Code Playgroud)

编辑

这种方法几乎可行:

.eab <- function(e)  eval(quote(list(a, b)), envir = e)
dt[, .eab(dt)]
Run Code Online (Sandbox Code Playgroud)

有两个缺点:(1)不返回列名,(2)dt必须明确传递(我宁愿避免).我宁愿避免硬编码dt作为选择环境.这些考虑导致了另一种提出上述问题的方式:是否有一种dt从内部获取环境的程序化方法.eab

Mat*_*wle 5

目的是创建一个表达式而不是一个函数。

DT[, list(a,b), by=...]  # ok

.ab = quote(list(a, b))    # simpler here, no need for function()

DT[, eval(.ab), by=...]  # same
Run Code Online (Sandbox Code Playgroud)

这种方法是data.table中分组快速的原因之一:j在静态环境中对所有组进行评估,因此可以避免每个函数调用的(较小)开销。

但是,如果.ab由于某种原因确实需要将其作为函数,那么我们当然可以进一步考虑一下。


use*_*457 2

警告,如果内部机制发生[.data.table变化,这可能不稳健、缓慢和/或容易中断,但如果由于某种原因无法解决它,这里有一个函数似乎可以满足您的要求。by我还可以想象,如果您开始使用其他选项(例如中的),它就不起作用[.data.table

.eab <- function() {
  foo <- quote(list(a,b))
  ans <- eval(foo, envir = parent.frame(3)$x)
  names(ans) <- vapply(as.list(foo)[-1], deparse, character(1))
  ans
}

identical(dt[, .eab()], dt[, list(a,b)])
# TRUE
Run Code Online (Sandbox Code Playgroud)

同样,这会颠覆/减少大量有充分理由存在的代码。