在聚合时遇到了data.table的以下问题,使用.SD并指定lapply,并从lapply explicitely声明FUN参数.这是出乎意料的行为,还是我错过了什么.为什么我不能在lapply中明确说明FUN?以下是可重现的示例.
require(data.table)
dt <- as.data.table(iris)
dt$Sepal.Length[sample(1:nrow(dt), 10)] <- NA
dt[, lapply(.SD, function(x) sum(!is.na(x), na.rm=TRUE)), by = Species]
Species Sepal.Length Sepal.Width Petal.Length Petal.Width
1: setosa 47 50 50 50
2: versicolor 46 50 50 50
3: virginica 47 50 50 50
dt[, lapply(.SD, FUN=function(x) sum(!is.na(x), na.rm=TRUE)), by = Species]
Error in ..FUN(FUN = Sepal.Length) :
unused argument(s) (FUN = Sepal.Length)
Run Code Online (Sandbox Code Playgroud)
归档为bug:#4839.(Arun现在在v1.8.9修复)
我不认为你错过任何东西.您应该在此处提交链接到此帖子的错误.接得好!
发生这种情况的原因是,当您使用lapply
with .SD
(in j
)时,data.table
尝试查找是否有一种方法可以在可能的情况下优化由于函数调用引起的开销.但是,在此过程中,而不是调用函数:
..FUN(Sepal.Length)
Run Code Online (Sandbox Code Playgroud)
在哪里..FUN = function(x) sum(!is.na(x), na.rm=TRUE)
,它变成:
..FUN(FUN = Sepal.Length)
Run Code Online (Sandbox Code Playgroud)
由于函数没有调用参数,FUN
因此它会返回错误.您可以通过在函数调用中更改x
为来验证这一点FUN
:
dt[, lapply(.SD, FUN=function(FUN) sum(!is.na(FUN), na.rm=TRUE)), by = Species]
# Species Sepal.Length Sepal.Width Petal.Length Petal.Width
# 1: setosa 49 50 50 50
# 2: versicolor 44 50 50 50
# 3: virginica 47 50 50 50
Run Code Online (Sandbox Code Playgroud)
内部:通过查看[.data.table
函数,解决此问题的一种方法是重写行:
txt <- as.list(jsub)[-1L]
# [[1]]
# .SD
# $FUN <~~~~ this name FUN gets caught up in building the expression later
# function(x) sum(!is.na(x), na.rm = TRUE)
Run Code Online (Sandbox Code Playgroud)
有:
txt <- as.list(jsub)[-1L]
names(txt)[2] <- ""
# [[1]]
# .SD
# [[2]]
# function(x) sum(!is.na(x), na.rm = TRUE)
Run Code Online (Sandbox Code Playgroud)
运行CHECK
成功完成.