为什么dcast不接受x [length(x)]?

时间:2019-09-17 16:13:57

标签: r data.table reshape2

我一直在努力通过获取最后一个元素来汇总dcast。这是一个示例:

x <- data.table::data.table(foo = "bar", value = c(1, 0))
x

#    foo value
# 1: bar     1
# 2: bar     0
data.table::dcast(x, ... ~ foo, fun.aggregate = function(x) x[length(x)])

# Error: Aggregating function(s) should take vector inputs and return a single value (length=1).
# However, function(s) returns length!=1. This value will have to be used to fill any missing
# combinations, and therefore must be length=1. Either override by setting the 'fill' argument
# explicitly or modify your function to handle this case appropriately.

reshape2的{​​{1}}版本中,以及使用dcast而不是data.frame时,也会发生这种情况。

有几种方法可以使它起作用。例如,我可以使用

data.table

并获得预期的结果。 data.table::dcast(x, ... ~ foo, fun.aggregate = function(x) rev(x)[1L]) # . bar # 1: . 0 函数也有效,dplyr::last()无效。

但是,我感兴趣的是为什么无法使用data.table::last()。如果我在聚合函数中放入中间的打印命令来确定正在发生的事情,则会得到以下信息:

x[length(x)]

这表明data.table::dcast(x, ... ~ foo, fun.aggregate = function(x) {print(x); print(length(x)); 5L}, value.var = "value") # numeric(0) # [1] 0 # [1] 1 0 # [1] 2 # . bar # 1: . 5 正在遍历表中没有的dcast值,并且由于foo是一个简单的字符向量,而不是一个因素,因此不能在其他位置存在向量。发生什么事了?

foo版本:3.6.0 R版本:1.12.2

1 个答案:

答案 0 :(得分:3)

似乎data.table::dcast.data.table()reshape2::dcast()都希望聚合函数返回长度0输入的长度1值。这两个函数都试图通过使用长度为0的参数调用聚合函数来获取要使用的“默认值”。

data.table代码的相关部分是here,如下所示:

fill.default = suppressWarnings(dat[0L][, eval(fun.call)])
if (nrow(fill.default) != 1L) stop(errmsg, call.=FALSE)

reshape2从plyr调用vaggregate(),它具有类似的部分here

.default <- .fun(.value[0], ...)

因此对于x[length(x)]来说,两个函数获得的默认值本质上是:

last <- function(x) x[length(x)]
last(numeric())
#> numeric(0)

即长度为0的向量。但是这两个函数都要求默认值的长度为1,因此会出现错误。

最后,dplyr::last()之所以有效,是因为它以长度为0的输入返回NA

dplyr::last(numeric())
#> [1] NA