首页 文章

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

提问于
浏览
8

考虑 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

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

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

理想情况下,我想获得从 [.data.table 通话摆脱 eval() ,并限制在的 .ab 而同时避免将数据表 dt 的功能 .ab 的定义 .

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

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

我怀疑's biting me is R'的词法范围以及 list(a,b) 的正确评估依赖于它在数据表 dt 的J环境中的事实 . 唉,我不知道如何获取对正确环境的引用,并将其用作 dt 中的 envirenclos 参数 .

# .eab <- function()  eval(quote(list(a, b)), envir = ?, enclos = ?)

EDIT

这种方法几乎可行:

.eab <- function(e)  eval(quote(list(a, b)), envir = e)
dt[, .eab(dt)]

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

2 回答

  • 2

    警告,如果 [.data.table 的内部机器发生变化,这可能是不稳定的,缓慢的和/或可能会中断,但如果由于某种原因,'s no way around it, here'的功能似乎符合您的要求 . 如果你开始在 [.data.table 中使用 by 等其他选项,我也可以想象它不起作用 .

    .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
    

    同样,这有很好的理由颠覆/减少了很多代码 .

  • 4

    目的是创建表达式而不是函数 .

    DT[, list(a,b), by=...]  # ok
    
    .ab = quote(list(a, b))    # simpler here, no need for function()
    
    DT[, eval(.ab), by=...]  # same
    

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

    但如果 .ab 由于某种原因确实需要成为一个函数,那么我们当然可以进一步思考 .

相关问题