由于长度检查不正确,R tapply()在data.frame上不起作用

时间:2020-10-11 19:41:16

标签: r dataframe tapply

这是一个错误报告,不是问题。报告R core中的错误的过程看起来很复杂,我不想成为邮件列表的一部分。因此,我要在此发布(如https://www.r-project.org/bugs.html.的建议)

这里是:

R 4.0.3的tapply()帮助在参数X上表示以下内容:

存在拆分方法的R对象。通常类似于矢量,允许使用[。

进行子集

问题:尽管可以拆分和子集化data.frame,但该R对象不能是data.frame。

要复制,请运行以下命令:

func <- function(dt) {
    sum(dt[,1] * dt[,2])
}

tab <- data.frame(x = sample(100), y = sample(100), z = sample(letters[1:10], 100, T))

tapply(tab[,1:2], INDEX = tab$z, FUN = func)

这导致

tapply(tab [,1:2],INDEX = tab $ z,FUN = func)中的错误: 参数必须具有相同的长度

在查看tapply()源代码后,似乎是由以下检查导致的:

 if (!all(lengths(INDEX) == length(X))) 
        stop("arguments must have same length")

但是length()不是要调用data.frame以确定其是否具有合适的分割尺寸的相关函数。应该使用nrow()

将上面的代码替换为

  if(is.data.frame(X)) {
     len <- nrow(X)
  } else {
        len <- length(X)
  }
  if (!all(lengths(INDEX) == len)) 
        stop("arguments must have same length")

解决错误。

此修补程序看起来非常简单,实现该修补程序将大大提高tapply()的实用性(我知道tapply()会有很多强大的选择),所以我想知道当前的限制是否反映了一种设计选择。

1 个答案:

答案 0 :(得分:1)

基于功能,我们可以使用

library(dplyr)
tab %>% 
     group_by(z) %>%
     summarise(new = func(cur_data()), .groups = 'drop')

-输出

# A tibble: 10 x 2
#   z       new
#   <chr> <int>
# 1 a     26647
# 2 b     28010
# 3 c     31340
# 4 d     20780
# 5 e     33311
# 6 f     31880
# 7 g     37527
# 8 h      8752
# 9 i     15490

或使用by中的base R

by(tab[, 1:2], tab$z, FUN = func)

根据?tapply

X-一个存在拆分方法的R对象。通常类似于矢量,允许使用[。

进行子集

此处,tab[, 1:2]是一个数据帧,而不是vector。如果它是matrix,它将是具有vector属性的dim