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

18

我在使用 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)

我收到以下错误:

Error in sum(v1, na.rm = TRUE) : invalid 'type' (character) of argument

现在,v1v2都作为字符变量从其他程序传递,因此我无法执行v1<- quote(Sepal.Length),尽管它似乎有效。


10
这个可能会让你找到正确的方向:dt[, sum(get(v1), na.rm=TRUE), by=v2],或者如果你可以灵活一些,建议采用其他方法。 - flodel
谢谢。它起作用了,发生了什么?函数获取名为v1的对象。替换函数对这个表达式做了什么?它没有做任何事情,试图用字符值"Sepal.Length"替换v1吗? - user1157129
1个回答

22

在评论中,替代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)来实现。当在j中使用get()时,被使用的列对all.vars不可见,因此如果j表达式需要它们,data.table将回退到对所有列进行子集处理(就像在j中使用.SD符号时一样,为此添加了.SDcols来解决)。如果仍然使用所有列,那么没有区别,但如果DT例如为1e7x100,则分组的j=sum(V1)应该比分组的j=sum(get("V1"))快得多。至少,这就是预期发生的事情,如果没有发生,那么可能是一个bug。另一方面,如果动态构建并重复许多查询,则paste0parse的时间可能会变长。真正取决于具体情况。设置verbose=TRUE应该会打印出有关j检测到使用了哪些列的消息,因此可以进行检查。


谢谢,回到原问题,使用您的解决方案如何实现这一点 getResult <- function(dt, expr, gby) { print(dt[,eval(expr), by=eval(b)]) } v1 <- "Sepal.Length" v2 <- "Species" e <- parse(text = paste("sum(", v1, ", na.rm = TRUE)")) b <- parse(text = v2) #rDT2 <- dt[, eval(e), by = eval(b)] dtR <- getResult(dt, e, b) - user1157129
@user1157129,非常抱歉在你的问题中遗漏了函数。请查看编辑后的建议。 - BenBarnes
@user1157129,将您上面的代码复制并插入换行符(同时加载data.table包),在我使用R 2.15.0和data.table 1.8.0时可以正常工作 - 您是否收到错误消息?什么没有起作用? - BenBarnes
1
@user1157129,我在使用R 2.13.1 patched和data.table 1.7.10时遇到了这个错误 - 你能否升级到这两个软件包的最新版本? - BenBarnes
1
是的,升级到R 2.15和data.table 1.8解决了这个问题。感谢Ben的帮助! - user1157129
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接