在R data.table中,如何将变量参数传递给表达式?

use*_*129 18 r parameter-passing data.table

我遇到了一个小问题data.table.非常感谢您的帮助.我该怎么做呢:

getResult <- function(dt, expr, gby) {
  e <- substitute(expr)
  b <- substitute(gby)
  return(dt[,eval(e),by=b])
}

v1 <- "Sepal.Length"
v2 <- "Species"

dt <- data.table(iris)
rDT <- getResult(dt, sum(v1, na.rm=TRUE), v2)
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

sum中的错误(v1,na.rm = TRUE):参数的'type'(字符)无效

现在,无论是v1v2从其他程序通过为字符型变量,所以我不能做到这一点v1<- quote(Sepal.Length),这似乎工作.

Ben*_*nes 21

在评论中替代flodel的答案可能是

e <- parse(text = paste0("sum(", v1, ", na.rm = TRUE)"))

b <- parse(text = v2)

rDT2 <- dt[, eval(e), by = eval(b)]

#               b    V1
# [1,]     setosa 250.3
# [2,] versicolor 296.8
# [3,]  virginica 329.4
Run Code Online (Sandbox Code Playgroud)

编辑:

把它放到一个函数中,

getResult <- function(dt, expr, gby){
  return(dt[, eval(expr), by = eval(gby)])
}

(dtR <- getResult(dt = dt, expr = e, gby = b))
# gives the same result as above
Run Code Online (Sandbox Code Playgroud)


来自马修的编辑: 有一个微妙的原因,为什么paste0eval\ quote方法可以比get在某些情况下更快.分组可以快速的原因之一是data.table检查j它使用哪些列,然后仅对那些使用的列进行子集(FAQ 1.12和3.1).它base::all.vars(j)用来做到这一点.当使用get()j被使用的从隐藏在柱all.varsdata.table回退到子集划分中的所有列,以防万一j表达需要它们时(很像.SD符号被用于在j,为此,.SDcols加入到解决).如果所有列都被使用,那么它没有什么区别,但如果DT说1e7x100那么分组j=sum(V1)应该比分组快得多j=sum(get("V1")).至少,那是应该发生的事情,如果没有,那么它可能是一个错误.另一方面,如果正在动态构建许多查询并重复这些查询,那么时间paste0parse可能会进入它.一切都取决于.设置verbose=TRUE应打印出有关已检测到哪些列的消息j,以便进行检查.