我试图回答 this nice question 关于为 data.table 对象创建非标准评估函数,进行分组求和。 Akrun 提出了一个可爱的答案,我将在这里简化:
akrun <- function(data, var, group){
var <- substitute(var)
group <- substitute(group)
data[, sum(eval(var)), by = group]
}
library(data.table)
mt = as.data.table(mtcars)
akrun(mt, cyl, mpg)
# group V1
# 1: 6 138.2
# 2: 4 293.3
# 3: 8 211.4
我也在研究一个答案,并且接近相同的答案,但是
substitute
s 与其余的内联。我的结果是一个错误:gregor = function(data, var, group) {
data[, sum(eval(substitute(var))), by = substitute(group)]
}
gregor(mt, mpg, cyl)
# Error in `[.data.table`(data, , sum(eval(substitute(var))), by = substitute(group)) :
# 'by' or 'keyby' must evaluate to vector or list of vectors
# (where 'list' includes data.table and data.frame which are lists, too)
从表面上看,我的功能是对 Akrun 的简单替换。为什么不起作用?
请注意,这两种替换都会导致问题,如下所示:
gregor_1 = function(data, var, group) {
var = substitute(var)
data[,sum(eval(var)),
by = substitute(group)]
}
gregor_1(mt, mpg, cyl)
# Same error as above
gregor_2 = function(data, var, group) {
group = substitute(group)
data[,sum(eval(substitute(var))),
by = group]
}
gregor_2(mt, mpg, cyl)
# Error in eval(substitute(var)) : object 'mpg' not found
最佳答案
在 substitute
的文档中,您可以阅读它如何决定替换的内容,
事实上,默认情况下,它会搜索调用它的环境。
如果您在 substitute
框架内调用 data.table
(即内部 []
)
它将无法找到符号,因为它们不存在于 data.table
评估环境中,
它们位于调用 [
的环境中。
您可以“反转”调用函数的顺序以获得您想要的行为:
library(data.table)
foo <- function(dt, group, var) {
eval(substitute(dt[, sum(var), by = group]))
}
foo(as.data.table(mtcars), cyl, mpg)
cyl V1
1: 6 138.2
2: 4 293.3
3: 8 211.4
关于r - 为什么 `substitute` 可以在多行中工作,而不能在单行中工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58649510/