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

时间:2012-05-20 16:29:24

标签: r parameter-passing data.table

我遇到data.table的小R问题。非常感谢您的帮助。我该怎么做:

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)

我收到以下错误:

  

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

现在,v1v2都从其他程序传递为字符变量,因此我无法执行此操作v1<- quote(Sepal.Length)

1 个答案:

答案 0 :(得分: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

修改

并将其置于一个函数中,

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


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