这种类型的问题(需要通过分组变量计算)在 StackOverflow 上被问了很多。我决定展示几种不同的方法来获得(几乎)相同的结果。
数据
首先我生成了一些简单的数据:
set.seed(123)
dat <- data.frame(group = sample(c('a','b','c'), 100, T),
value = rnorm(100),
stringsAsFactors = FALSE)
head(dat)
# group value
# 1 a 0.25331851
# 2 c -0.02854676
# 3 b -0.04287046
# 4 c 1.36860228
# 5 c -0.22577099
# 6 a 1.51647060
聚合示例
我将介绍一些执行聚合的不同方法:by、aggregate、lapply 和 split、tapply、dplyr 和 data.table。
要使用by函数,我们传入一些data,并给它我们想要分组的变量,然后我们传递我们想要应用的函数,然后我使用stack在表格中获取它表格。
stack(by(dat, dat$group, function(d) mean(d$value)))
# values ind
# 1 0.05444944 a
# 2 -0.16894993 b
# 3 -0.04324673 c
要使用aggregate 函数,我们可以使用公式语法,并给它我们的数据和我们想要的函数。我非常喜欢aggregate。
aggregate(value ~ group, data = dat, mean)
# group value
# 1 a 0.05444944
# 2 b -0.16894993
# 3 c -0.04324673
我们可以使用split和lapply先通过我们的分组变量将数据分开,然后对分开的列表进行计算。我们使用stack 将结果以表格形式呈现。
stack(lapply(split(dat, dat$group), function(d) mean(d$value)))
# values ind
# 1 0.05444944 a
# 2 -0.16894993 b
# 3 -0.04324673 c
我们可以使用tapply 函数将函数应用于不规则数组。我们给它我们想要用于计算的变量、我们的分组变量和我们的函数。我们使用stack 将结果以表格形式呈现。
stack(tapply(dat$value, dat$group, mean))
# values ind
# 1 0.05444944 a
# 2 -0.16894993 b
# 3 -0.04324673 c
我们也可以使用出色的 dplyr 包来执行聚合。我们首先使用group_by 对数据进行分组,然后使用summarise 应用我们的函数。 %>% 符号是管道 - 它们非常有用。
library(dplyr)
dat %>%
group_by(group) %>%
summarise(mean(value))
# group `mean(value)`
# <chr> <dbl>
# 1 a 0.05444944
# 2 b -0.16894993
# 3 c -0.04324673
最后,我们可以使用高性能的data.table包来执行聚合。语法起初可能看起来有点奇怪,但我们基本上是在说:计算按组分组的平均值。
library(data.table)
setDT(dat)[,mean(value),group]
# group V1
# 1: a 0.05444944
# 2: c -0.04324673
# 3: b -0.16894993