最好通过示例
来说明str(mtcars)
mtcars$gear <- factor(mtcars$gear, labels=c("three","four","five"))
mtcars$cyl <- factor(mtcars$cyl, labels=c("four","six","eight"))
mtcars$am <- factor(mtcars$am, labels=c("manual","auto")
str(mtcars)
tapply(mtcars$mpg, mtcars$gear, sum)
这给了我每个档位的加总mpg。但是我想要一个3x3的桌子,顶部有齿轮,侧面有圆柱体,而且有两个总和的9个单元格,我怎么能“聪明地”得到它。
我可以去。
tapply(mtcars$mpg[mtcars$cyl=="four"], mtcars$gear[mtcars$cyl=="four"], sum)
tapply(mtcars$mpg[mtcars$cyl=="six"], mtcars$gear[mtcars$cyl=="six"], sum)
tapply(mtcars$mpg[mtcars$cyl=="eight"], mtcars$gear[mtcars$cyl=="eight"], sum)
这看起来很麻烦。
然后我如何在混音中加入第三个变量?
这有点在我正在考虑的空间中。 Summary statistics using ddply
更新这让我在那里,但它并不漂亮。
aggregate(mpg ~ am+cyl+gear, mtcars,sum)
干杯
答案 0 :(得分:35)
这个怎么样,还在使用tapply()
?它比你知道的更多才多艺!
with(mtcars, tapply(mpg, list(cyl, gear), sum))
# three four five
# four 21.5 215.4 56.4
# six 39.5 79.0 19.7
# eight 180.6 NA 30.8
或者,如果您希望打印输出更具解释性:
with(mtcars, tapply(mpg, list("Cylinder#"=cyl, "Gear#"=gear), sum))
如果你想使用两个以上的交叉分类变量,这个想法完全相同。然后,结果将以3维或更多维的数组返回:
A <- with(mtcars, tapply(mpg, list(cyl, gear, carb), sum))
dim(A)
# [1] 3 3 6
lapply(1:6, function(i) A[,,i]) # To convert results to a list of matrices
# But eventually, the curse of dimensionality will begin to kick in...
table(is.na(A))
# FALSE TRUE
# 12 42
答案 1 :(得分:8)
我认为已经在这个问题上的答案是很棒的选择,但我想根据dplyr
包分享一个额外的选项(这对我来说是因为我现在正在教我们使用的课程dplyr
用于数据操作,因此我希望避免向学生介绍tapply
或aggregate
等专业基础R函数。
您可以使用group_by
功能将任意数量的变量分组,然后使用summarize
汇总这些组中的信息。我认为这个代码对于R新手来说比aggregate
的基于公式的界面更具可读性,产生相同的结果:
library(dplyr)
mtcars %>%
group_by(am, cyl, gear) %>%
summarize(mpg=sum(mpg))
# am cyl gear mpg
# (dbl) (dbl) (dbl) (dbl)
# 1 0 4 3 21.5
# 2 0 4 4 47.2
# 3 0 6 3 39.5
# 4 0 6 4 37.0
# 5 0 8 3 180.6
# 6 1 4 4 168.2
# 7 1 4 5 56.4
# 8 1 6 4 42.0
# 9 1 6 5 19.7
# 10 1 8 5 30.8
使用两个变量,您可以通过添加spread
包中tidyr
函数的调用来汇总行上的一个变量和列上的另一个变量:
library(dplyr)
library(tidyr)
mtcars %>%
group_by(cyl, gear) %>%
summarize(mpg=sum(mpg)) %>%
spread(gear, mpg)
# cyl 3 4 5
# (dbl) (dbl) (dbl) (dbl)
# 1 4 21.5 215.4 56.4
# 2 6 39.5 79.0 19.7
# 3 8 180.6 NA 30.8
答案 2 :(得分:4)
我喜欢Josh的答案,但是reshape2
也可以为这些类型的问题提供一个很好的框架:
library(reshape2)
#use subset to only grab the variables of interest...
mtcars.m <- melt(subset(mtcars, select = c("mpg", "gear", "cyl")), measure.vars="mpg")
#cast into appropriate format
dcast(mtcars.m, cyl ~ gear, fun.aggregate=sum, value.var="value")
cyl three four five
1 four 21.5 215.4 56.4
2 six 39.5 79.0 19.7
3 eight 180.6 0.0 30.8
答案 3 :(得分:3)
答案包含使用tapply和aggregate函数的相同输出。
我想在Josh O'Brien的回答中添加一些信息。用户可以使用聚合函数或tapply,具体取决于输出。为了在tapply中使用多个因子变量,可以使用Josh所示的方法。
加载数据集
data("mtcars")
使用tapply
with(mtcars, tapply(mpg, list("Cylinder#"=cyl, "Gear#"=gear), sum))
上述代码的输出是
Gear#
Cylinder# 3 4 5
4 21.5 215.4 56.4
6 39.5 79.0 19.7
8 180.6 NA 30.8
使用聚合函数
with(mtcars, aggregate(mpg, list(Cylinder = cyl, Gear = gear), sum))
汇总功能的输出
Cylinder Gear x
1 4 3 21.5
2 6 3 39.5
3 8 3 180.6
4 4 4 215.4
5 6 4 79.0
6 4 5 56.4
7 6 5 19.7
8 8 5 30.8
现在,如果用户想要与聚合函数相同的输出,但使用tapply。
as.data.frame(as.table(with(mtcars, tapply(mpg, list("Cylinder#"=cyl, "Gear#"=gear),
sum))))
tapply函数的输出
Cylinder. Gear. Freq
1 4 3 21.5
2 6 3 39.5
3 8 3 180.6
4 4 4 215.4
5 6 4 79.0
6 8 4 NA
7 4 5 56.4
8 6 5 19.7
9 8 5 30.8
可以根据业务要求保留或删除NA。