R中的汇总/聚合而不丢弃级别

时间:2014-01-06 20:11:06

标签: r aggregate summarization

我想在不丢弃空白级别的情况下总结或聚合表格。我想知道是否有人对此有任何想法?

举个例子, 这是一个数据框

df1<-data.frame(Method=c(rep("A",3),rep("B",2),rep("C",4)),
       Type=c("Fast","Fast","Medium","Fast","Slow","Fast","Medium","Slow","Slow"),
            Measure=c(1,1,2,1,3,1,1,2,2))

使用base和doBy包的两种方法。

#base
aggregate(Measure~Method+Type,data=df1,FUN=length)

require(doBy)
summaryBy(Measure~Method+Type,data=df1,FUN=length)

他们都给出了不同排序的相同结果,但问题是我希望将所有方法和类型的组合以及缺少的度量作为NA插入。或者必须保持我所有因素的所有水平。

df1$Type
df1$Method

也许plyr有一些东西,但我不知道它是如何运作的。

5 个答案:

答案 0 :(得分:4)

查看tapply

with(df1, tapply(Measure, list(Method, Type), FUN = length))

#   Fast Medium Slow
# A    2      1   NA
# B    1     NA    1
# C    1      1    2

答案 1 :(得分:1)

在基数R中,by将返回缺失值的结果。

result <- by(df1, INDICES=list(df1$Method, df1$Type), FUN=nrow)
cbind(expand.grid(attributes(result)$dimnames), as.vector(result))

#   Var1   Var2 as.vector(result)
# 1    A   Fast                 2
# 2    B   Fast                 1
# 3    C   Fast                 1
# 4    A Medium                 1
# 5    B Medium                NA
# 6    C Medium                 1
# 7    A   Slow                NA
# 8    B   Slow                 1
# 9    C   Slow                 2

答案 2 :(得分:1)

您可以在基地R中尝试by()。例如,

tab <- with(df1, by(df1, list(Method = Method, Type = Type), FUN = length))
Method: A
Type: Fast
[1] 2
------------------------------------------------------------ 
Method: B
Type: Fast
[1] 1
------------------------------------------------------------ 
Method: C
Type: Fast
[1] 1
------------------------------------------------------------ 
Method: A
Type: Medium
[1] 1
------------------------------------------------------------ 
Method: B
Type: Medium
[1] NA
------------------------------------------------------------ 
Method: C
Type: Medium
[1] 1
------------------------------------------------------------ 
Method: A
Type: Slow
[1] NA
------------------------------------------------------------ 
....

请注意,这只是print()方法,使其看起来很复杂。如果我们unclass() tab,我们会在这个例子中看到它只是一个多方位表:

R> unclass(tab)
      Type
Method Fast Medium Slow
     A    2      1   NA
     B    1     NA    1
     C    1      1    2
attr(,"call")
by.data.frame(data = df1, INDICES = list(Method = Method, Type = Type), 
    FUN = nrow)

你可以使用它,因为它只是一个数组(矩阵)。如果你喜欢长格式,你可以轻松解开它:

nr <- nrow(tab)
ltab <- cbind.data.frame(Method = rep(rownames(tab), times = nr),
                         Type = rep(colnames(tab), each = nr),
                         Count = c(tab))
ltab

R> ltab
  Method   Type Count
1      A   Fast     2
2      B   Fast     1
3      C   Fast     1
4      A Medium     1
5      B Medium    NA
6      C Medium     1
7      A   Slow    NA
8      B   Slow     1
9      C   Slow     2

答案 3 :(得分:0)

感谢您的回答。我认为所有这些都可以给出结果。但Mark Heckmann对此代码的评论

ddply(df1, .(Method, Type), summarise, Measure=length(Measure), .drop=F)

似乎提供了一个很好的干净输出数据框,具有良好的标头和最少的代码。在缺点方面,它需要额外的包装。

答案 4 :(得分:0)

2021 年更新

我认为现在可以通过使用 stats::aggregate()drop = FALSE 来完成。不需要额外的包裹。结果是一个常规的 ole 数据帧,其中空级别为 NA

aggregate(Measure ~ Method + Type, data = df1, FUN = length, drop = FALSE)

  Method   Type Measure
1      A   Fast       2
2      B   Fast       1
3      C   Fast       1
4      A Medium       1
5      B Medium      NA
6      C Medium       1
7      A   Slow      NA
8      B   Slow       1
9      C   Slow       2