TL; DR:当fun.aggregate
的调用是在一个函数内完成的dcast.data.table
时,如何将dcast.data.table
传递给fun.aggregate
?
我有一张这样的表:
library(data.table)
t <- data.table(id=rep(1:2, c(3,4)), k=c(rep(letters[1:3], 2), 'c'), v=1:7)
t
id k v
1: 1 a 1
2: 1 b 2
3: 1 c 3
4: 2 a 4
5: 2 b 5
6: 2 c 6
7: 2 c 7 # note the duplicate (2, c)
我重塑为长格式,保留重复的最后一次出现
dcast.data.table(t, id ~ k, value.var='v', fun.aggregate=last) # last is in data.table
id a b c
1: 1 1 2 3
2: 2 4 5 7
但是,如果我将dcast.data.table
调用包装到函数中:
f <- function (tbl, fun.aggregate) {
dcast.data.table(tbl, id ~ k, value.var='v', fun.aggregate=fun.aggregate)
}
f(t, last)
Error in `[.data.table`(data, , eval(fun.aggregate), by = c(ff_)) :
could not find function "fun.aggregate"
看起来符号fun.aggregate
正在被评估(eval(fun.aggregate)
)而未找到(因为函数“fun.aggregate”不存在)。
我应该如何将我想要的fun.aggregate
传递给f
?
(我确定它与quote
,substitute
等有关,但我对这些功能非常困难,我通常只是将它们链接在一起,直到有效的方式。)
编辑:
> sessionInfo()
R version 3.1.0 (2014-04-10)
Platform: x86_64-pc-linux-gnu (64-bit)
...
other attached packages:
[1] data.table_1.9.3
哎呀,我刚刚意识到这个bug出现在1.9.3(开发版,我升级为避免无关的bug)和1.9.2(当前CRAN发行版)中的不。
我宁愿不降级到1.9.2(前面提到的我要避免的错误),所以通常有一种方法可以保护eval()
调用函数的参数吗?
答案 0 :(得分:4)
现在已在commit 1303 v 1.9.3中修复此问题 - 当前的开发版本。来自NEWS:
当从接受dcast.data.table
参数的函数中调用并传递给fun.aggregate
时,
fun.aggregate
正确处理dcast.data.table()
参数。关闭#713。感谢mathematicalcoffee在SO上报告here。
请注意dcast.data.table
中的另一个小疏忽现在已修复 - #715。
问题是last
函数不会为所有输入值生成长度为1的值 - 这是fun.aggregate
的要求。
last(integer(0))
# [1] integer(0)
如果未设置fill
参数,则此值是用于填充缺失组合的值。此案件之前没有被发现,但现在已经修复。
以下是(正确)行为的示例:
tt <- t[1:5] # t is from your example
dcast.data.table(tt, id ~ k, fun.aggregate=last)
# Error in dcast.data.table(tt, id ~ k, fun.aggregate = last) :
# Aggregating function provided to argument 'fun.aggregate' should always return
# a length 1 vector, but returns 0-length value for fun.aggregate(integer(0)).
# This value will have to be used to fill missing combinations, if any, and
# therefore can not be of length 0. Either override by setting the 'fill' argument
# explicitly or modify your function to handle this case appropriately.
dcast.data.table(tt, id ~ k, fun.aggregate=last, fill=NA)
# id a b c
# 1: 1 1 2 3
# 2: 2 4 5 NA