当使用data.table进行分组时,为什么我不能在lapply中使用FUN

时间:2013-08-19 13:15:25

标签: r data.table lapply

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

1 个答案:

答案 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已成功完成。