我在使用.SD聚合时遇到了data.table的以下问题,并指定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)
Filed as bug: #4839。 (Arun现在在v1.8.9修复)
答案 0 :(得分:8)
我认为你没有遗漏任何东西。你应该提交一个链接到这篇文章的错误here。好抓!
这是因为,当您使用lapply
.SD
时(j
),data.table
会尝试查找是否有办法优化因函数调用而导致的开销可能。但是,在此过程中,而不是调用函数:
..FUN(Sepal.Length)
其中..FUN = function(x) sum(!is.na(x), na.rm=TRUE)
,它变为:
..FUN(FUN = Sepal.Length)
由于该函数没有名为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
内部:通过查看[.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)
使用:
txt <- as.list(jsub)[-1L]
names(txt)[2] <- ""
# [[1]]
# .SD
# [[2]]
# function(x) sum(!is.na(x), na.rm = TRUE)
正在运行CHECK
已成功完成。