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

7 r lapply data.table

在聚合时遇到了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修复)

Aru*_*run 8

我不认为你错过任何东西.您应该在此处提交链接到此帖子的错误.接得好!

发生这种情况的原因是,当您使用lapplywith .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成功完成.

  • +1很好发现和修好Arun.现在致力于v1.8.9. (2认同)