data.table ..用j中的函数表示

时间:2018-02-14 22:11:48

标签: r data.table

我正在尝试使用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}}来实现结果,但我想知道我在大多数情况下都在使用最佳实践。

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')