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'(字符)无效
现在,无论是v1
和v2
从其他程序通过为字符型变量,所以我不能做到这一点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)
来自马修的编辑:
有一个微妙的原因,为什么paste0
和eval
\ 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"))
.至少,那是应该发生的事情,如果没有,那么它可能是一个错误.另一方面,如果正在动态构建许多查询并重复这些查询,那么时间paste0
和parse
可能会进入它.一切都取决于.设置verbose=TRUE
应打印出有关已检测到哪些列的消息j
,以便进行检查.