汇总/在 R 中聚合而不降低级别
Posted
技术标签:
【中文标题】汇总/在 R 中聚合而不降低级别【英文标题】:Summary / Aggregate in R without dropping levels 【发布时间】:2014-01-24 08:30:38 【问题描述】:我想在不删除空级别的情况下汇总或汇总表格。我想知道是否有人对此有任何想法?
例如, 这是一个数据框
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
有一些东西,但我不知道它是如何工作的。
【问题讨论】:
见similar question with data.table 另见ddply
它是 .drop
参数。
正如@joran 已经说过的,但你不熟悉 plyr:ddply(df1, .(Method, Type), summarise, Measure=length(Measure), .drop=F)
乔兰和马克。那很完美。谢谢。这个选项“总结”从何而来?当最常见的用法是“FUN=length”时,“Measure=length(Measure)”。我无法从糟糕的帮助页面 ?ddply 中弄清楚这些简单的事情。再次感谢大家。
【参考方案1】:
看看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
【讨论】:
【参考方案2】:在基础 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
【讨论】:
【参考方案3】:您可以尝试在 base 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
【讨论】:
不是吹毛求疵,而是返回每个分组的列数,而不是观察数。 @MatthewPlourde 谢谢马修,只是为了表明我不应该在这里和推特上回答问题并同时工作......!【参考方案4】:感谢您的回答。我认为他们都努力给出结果。但是 Mark Heckmann 对此代码的评论
ddply(df1, .(Method, Type), summarise, Measure=length(Measure), .drop=F)
似乎提供了一个漂亮干净的输出数据帧,具有良好的标头和最少的代码。不利的一面是,它需要额外的软件包。
【讨论】:
【参考方案5】: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
【讨论】:
以上是关于汇总/在 R 中聚合而不降低级别的主要内容,如果未能解决你的问题,请参考以下文章
如何根据使用 dplyr 的组上的聚合函数计算新列(在汇总统计信息上添加汇总统计信息)?
R语言dplyr包获取dataframe分组聚合汇总统计值实战(group_by() and summarize() ):均值中位数分位数IQRMADcountunique