包data.table
具有一些特殊的语法,需要使用表达式作为i
和j
参数。
这对于编写接受并传递参数到数据表的函数有一些影响,如常见问题解答的第1.16节所详细解释的那样。
但我无法想象如何把它提高到另一个级别。
以下是一个示例。假设我想编写一个包装器函数foo()
,对我的数据进行特定汇总,然后再编写一个调用foo()
并绘制结果的第二个包装器plotfoo()
:
library(data.table)
foo <- function(data, by){
by <- substitute(by)
data[, .N, by=list(eval(by))]
}
DT <- data.table(mtcars)
foo(DT, gear)
好的,这个可行,因为我得到了我的表格结果:
by N
1: 4 12
2: 3 15
3: 5 5
现在,当我写 plotfoo()
时,我尝试做到与之前完全相同,但是我失败了:
plotfoo <- function(data, by){
by <- substitute(by)
foo(data, eval(by))
}
plotfoo(DT, gear)
但是这一次我收到了一个错误信息:
Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
好的,eval()
函数造成了问题。让我们把它移除:
plotfoo <- function(data, by){
by <- substitute(by)
foo(data, by)
}
plotfoo(DT, gear)
哦不,我收到了一个新的错误信息:
Error in `[.data.table`(data, , .N, by = list(eval(by))) :
column or expression 1 of 'by' or 'keyby' is type symbol. Do not quote column names. Useage: DT[,sum(colC),by=list(colA,month(colB))]
而这就是我卡住的地方。
问题:如何编写一个调用函数和调用data.table的函数?
substitute(by)
和eval
并将gear
作为字符变量传递,例如foo(DT, "gear")
,那么两者都可以工作。 - Arun