首页 文章

为什么tapply中的参数FUN与colwise结合无效

提问于
浏览
0

我通常使用 colwisetapply 的组合来计算数据框中的分组值 . 但是,我意外地发现 tapply 中的参数 FUN 无法与 plyr 中的 colwise 一起正常工作 . 示例如下:

数据:

df <- data.frame(a = 1:10, b = rep(1:2, each = 5), c = 2:11)

正常:

library(plyr)
colwise(tapply)(subset(df, select = c(a, c)), df$b, function(x){sum(x[x > 2])})

以上代码是正确的,可以正常工作 . 但如果我添加 FUN ,那就错了:

colwise(tapply)(subset(df, select = c(a, c)), df$b, FUN = function(x){sum(x[x > 2])})

错误是:

Error in FUN(X[[1L]], ...) : 

unused arguments (function (X, INDEX, FUN = NULL, ..., simplify = TRUE) 
{
    FUN <- if (!is.null(FUN)) match.fun(FUN)
    if (!is.list(INDEX)) INDEX <- list(INDEX)
    nI <- length(INDEX)
    if (!nI) stop("'INDEX' is of length zero")
    namelist <- vector("list", nI)
    names(namelist) <- names(INDEX)
    extent <- integer(nI)
    nx <- length(X)
    one <- 1
    group <- rep.int(one, nx)
    ngroup <- one
    for (i in seq_along(INDEX)) {
        index <- as.factor(INDEX[[i]])
        if (length(index) != nx) stop("arguments must have same length")
        namelist[[i]] <- levels(index)
        extent[i] <- nlevels(index)
        group <- group + ngroup * (as.integer(index) - one)
        ngroup <- ngroup * nlevels(index)
    }
    if (is.null(FUN)) return(group)
    ans <- lapply(X = split(X, group), FUN = FUN, ...)
    index <- as.integer(names(ans))
    if (simplify && all(unlist(lapply(ans, length)) == 1)) {
        ansmat <- array(dim = extent, dimnames = namelist)

谁有人解释原因?先感谢您 .

1 回答

  • 0

    好吧,问题是 lapplytapply 都有一个可选的 FUN 参数 . 请注意 colwise(tapply) 是一个包含以下行的函数:

    out <- do.call("lapply", c(list(filtered, .fun, ...), dots))
    

    让我们通过写一下我们的调试器

    ct <- colwise(tapply); trace(ct, quote(browser()), at = 6)
    

    然后跑

    ct(subset(df, select = c(a, c)), df$b, FUN = function(x){sum(x[x > 2])})
    

    现在让我们打印 c(list(filtered, .fun, ...), dots) . 请注意,前三个(未命名)参数现在是数据帧, tapplydb$b ,上面的 FUN 参数最后出现 . 但是,这个论点是命名的 . 由于这是 lapply 上的 do.call ,而不是该参数成为 tapply 的可选参数,它现在成为 lapply 的主要调用!所以发生的事情就是你把它变成了:

    lapply(subset(df, select = c(a, c)), function(x){sum(x[x > 2])}, tapply, df$b)
    

    当然,这没有任何意义,如果您手动执行上述操作(仍在调试器中),您将获得完全相同的错误 . 有关简单的解决方法,请尝试:

    tapply2 <- function(.FUN, ...) tapply(FUN = .FUN, ...)
    colwise(tapply2)(subset(df, select = c(a, c)), df$b, .FUN = function(x){sum(x[x > 2])})
    

    plyr 包应该检查名为 FUN... 参数(或者任何可能干扰 lapply 's job), but it doesn' t的内容似乎作者都包括此内容 . 您可以向执行以下任何变通办法的 plyr 包提交拉取请求:

    定义一个本地

    .lapply <- function(`*X*`, `*FUN*`, ...) lapply(X = `*X*`, `*FUN*`, ...)
    

    (进一步减少干扰) .

    检查 colwise(tapply) 函数中的 names(list(...)) 是否为 XFUN (如果作者打算在子调用之前阻止评估promises,则会引入问题) .

    使用名为 XFUN 显式调用 do.call("lapply", ...) ,以便获得预期

    formal argument "FUN" matched by multiple actual arguments
    

相关问题