R-ave vs tapply。总是唯一(ave)== tapply吗?如果是这样,为什么其中之一存在?

时间:2018-07-05 04:43:32

标签: r r-base

请考虑以下内容-

set.seed(1)
x <- runif(100)
y <- sample(c('M', 'F', 'D'), 100, TRUE)
aveResult <- ave(x = x, y, FUN = sum)
tapplyResult <- tapply(x, y, sum)
aveResult <- setNames(aveResult, y)
tapplyResult
aveResult[!duplicated(names(aveResult))]

这两个函数的结果除了输出长度相同外,其余均相同。此外,这还会造成混乱(由于回收而加剧),如this case

是否有一个示例,其中一个功能可以执行其他功能不能执行的操作?

2 个答案:

答案 0 :(得分:4)

ave是一个非常有用的base R函数,该函数可快速有效地基于按组应用功能创建新列(下面是一个简单的示例,可按组列创建mean使用avedplyrdata.table方法)。

set.seed(24)
df1 <- data.frame(grp = sample(LETTERS, 1e6, replace = TRUE), val = rnorm(1e6))
system.time(with(df1, ave(val, grp)))
#   user  system elapsed 
#  0.070   0.004   0.073 

library(dplyr)
system.time(df1 %>%
              group_by(grp) %>%
              mutate(new = mean(val)))
#   user  system elapsed 
#  0.159   0.000   0.160 

library(data.table)
system.time(setDT(df1)[, new := mean(val), by = grp])
#  user  system elapsed 
#  0.056   0.000   0.057 

tapply给出汇总输出。 ave的主要优点之一是,我们不必担心输出的顺序,因为它始终以与行相同的顺序提供输出。即使在某些tidyverse函数中,这也可以改变。 sort的{​​{1}} ed个unique值是否始终等于ave的问题-这取决于。对于某些功能,我们可以在tapply

中获得汇总的list输出
tapply

tapply(1:10, rep(LETTERS[1:3], c(3, 3, 4)), FUN = range) 在这里失败是因为它与每个组的长度都不匹配

ave

并给出警告

答案 1 :(得分:2)

在这种情况下,只需添加一个选项即可:还有by(x, y, FUN = sum)

作为@akrun出色文章的补充,以下是给定OP示例数据的avetapplyby之间的输出差异的简短细分:

  1. ave(x, y, FUN = sum)用组和值替换x项,其中每个组由具有相同x分量的那些y值组成。返回对象是长度为length(x)的向量。

  2. tapply(x, y, sum)对每个组求和x个值;返回对象是一个数组,其维数与y具有唯一组的维数相同。

  3. by(x, y, sum)还将每个组的x值相加;返回对象是一个列表,其条目数与具有唯一组的y相同。


考虑avetapply / by之间的区别的另一种方式是在dplyr语法的上下文中:

  1. ave对应于group_by + mutate语句:

    data.frame(x, y) %>% group_by(y) %>% mutate(x = sum(x)) %>% pull(x)
    
  2. tapply / by对应于group_by + summarise语句:

    data.frame(x, y) %>% group_by(y) %>% summarise(x = sum(x)) %>% pull(x)
    

正如@Onyambu所正确强调的那样,bytapply是完全不同的; tapply适用于vector,而by可以接受任何对象(通常是data.framematrix等)。