我正在尝试使用data.table' ..
表示函数,这是我到目前为止的代码:
set.seed(42)
dt <- data.table(
x = rnorm(10),
y = runif(10)
)
test_func <- function(data, var, var2) {
vars <- c(var, var2)
data[, ..vars]
}
test_func(dt, 'x', 'y') # this works
test_func2 <- function(data, var, var2) {
data[, ..var]
}
test_func2(dt, 'x', 'y') # this works too
test_func3 <- function(data, var, var2) {
data[, sum(..var)]
}
test_func3(dt, 'x', 'y')
# this does not work
# Error in eval(jsub, SDenv, parent.frame()) : object '..var' not found
data.table
似乎..
在j
中的另一个函数内被包裹后无法识别sum(get(var))
。我知道我可以使用{{1}}来实现结果,但我想知道我在大多数情况下都在使用最佳实践。
答案 0 :(得分:2)
Parroting an answer to a different problem也适用于此。这不是最漂亮的解决方案,但过去的变种在我看来已经无数次了。
在此感谢@Frank提供非parse()
解决方案!
我非常熟悉旧格言&#34;如果答案是解析(),你通常应该重新考虑这个问题。&#34; ,但我有我很难在 data.table
调用环境中进行评估时多次提出替代方案,我很乐意看到一个强大的解决方案,它不会执行作为字符串传入的任意代码。 事实上,我发布这样的答案的一半原因是希望有人可以推荐更好的选择。
test_func3 <- function(data, var, var2) {
expr = substitute(sum(var), list(var=as.symbol(var)))
data[, eval(expr)]
}
test_func3(dt, 'x', 'y')
## [1] 5.472968
使用eval(解析(...))对假设世界末日场景的快速免责声明
eval(parse(...))
的危险性远远超过in depth discussions,但我不会完全重复这些危险。
理论上,如果您的某个列被命名为"(system(paste0('kill ',Sys.getpid())))"
之类的不幸事件,您可能会遇到问题(请勿执行此操作,它会在现场终止您的R会话!)。这是除非你打算把它放在CRAN的一个包装中,否则可能有足够的外部机会不会失去睡眠。
对于下面评论中特定情况,表格被分组,然后sum
应用于所有,.SDcols
可能有用。我知道的唯一方法是确保即使dt
有一个名为var3
的列,此函数也会返回一致的结果,这是为了评估函数环境中的参数,但是在{使用data.table
的环境{1}}。
c()
返回
set.seed(42)
dt <- data.table(
x = rnorm(10),
y = rnorm(10),
z = sample(c("a","b","c"),size = 10, replace = TRUE)
)
test_func3 <- function(data, var, var2, var3) {
ListOfColumns = c(var,var2)
GroupColumn <- c(var3)
dt[, lapply(.SD, sum), by= eval(GroupColumn), .SDcols = ListOfColumns]
}
test_func3(dt, 'x', 'y','z')