提问人:user1289220 提问时间:3/24/2012 最后编辑:Maëluser1289220 更新时间:8/4/2023 访问量:304932
如何按组获取汇总统计信息
How to get summary statistics by group
问:
我正在尝试一次性获得 R/S-PLUS 中按分类列分组的多个汇总统计数据。我找到了几个函数,但它们每次调用都做一个统计信息,比如 .aggregate()
data <- c(62, 60, 63, 59, 63, 67, 71, 64, 65, 66, 68, 66,
71, 67, 68, 68, 56, 62, 60, 61, 63, 64, 63, 59)
grp <- factor(rep(LETTERS[1:4], c(4,6,6,8)))
df <- data.frame(group=grp, dt=data)
mg <- aggregate(df$dt, by=df$group, FUN=mean)
mg <- aggregate(df$dt, by=df$group, FUN=sum)
我正在寻找的是获取同一组的多个统计数据,例如平均值、最小值、最大值、标准值......等等,这可行吗?
答:
看一下包装。具体说来plyr
ddply
ddply(df, .(group), summarise, mean=mean(dt), sum=sum(dt))
首先,这取决于你的 R 版本。如果你已经通过了 2.11,你可以将 aggreggate 与多个结果函数(summary、by instance 或你自己的函数)一起使用。如果没有,您可以使用贾斯汀的答案。
有很多不同的方法可以解决这个问题,但我偏向于包中:describeBy
psych
describeBy(df$dt, df$group, mat = TRUE)
1. 申请
我会投入我的两分钱.tapply()
tapply(df$dt, df$group, summary)
您可以使用所需的特定统计信息编写自定义函数,也可以设置结果的格式:
tapply(df$dt, df$group,
function(x) format(summary(x), scientific = TRUE))
$A
Min. 1st Qu. Median Mean 3rd Qu. Max.
"5.900e+01" "5.975e+01" "6.100e+01" "6.100e+01" "6.225e+01" "6.300e+01"
$B
Min. 1st Qu. Median Mean 3rd Qu. Max.
"6.300e+01" "6.425e+01" "6.550e+01" "6.600e+01" "6.675e+01" "7.100e+01"
$C
Min. 1st Qu. Median Mean 3rd Qu. Max.
"6.600e+01" "6.725e+01" "6.800e+01" "6.800e+01" "6.800e+01" "7.100e+01"
$D
Min. 1st Qu. Median Mean 3rd Qu. Max.
"5.600e+01" "5.975e+01" "6.150e+01" "6.100e+01" "6.300e+01" "6.400e+01"
2. 数据表
该软件包为这些类型的操作提供了许多有用且快速的工具:data.table
library(data.table)
setDT(df)
> df[, as.list(summary(dt)), by = group]
group Min. 1st Qu. Median Mean 3rd Qu. Max.
1: A 59 59.75 61.0 61 62.25 63
2: B 63 64.25 65.5 66 66.75 71
3: C 66 67.25 68.0 68 68.00 71
4: D 56 59.75 61.5 61 63.00 64
评论
summary
tapply(df$dt, df$group, function(x) format(summary(x), scientific = TRUE))
data.table
此外,该软件包是另一种选择。它提供了 SAS PROC SUMMARY 的许多功能。细节: http://www.statmethods.net/stats/descriptives.htmldescribeBy
doBy
评论
freq
descr
dplyr 包可能是解决这个问题的不错替代方案:
library(dplyr)
df %>%
group_by(group) %>%
summarize(mean = mean(dt),
sum = sum(dt))
获得第一象限和第三象限
df %>%
group_by(group) %>%
summarize(q1 = quantile(dt, 0.25),
q3 = quantile(dt, 0.75))
使用 Hadley Wickham 的 purrr 包,这非常简单。用于将传递的函数拆分为多个组,然后用于将函数应用于每个组。split
data_frame
map
summary
library(purrr)
df %>% split(.$group) %>% map(summary)
评论
tapply
经过漫长的 5 年,我相信这个答案不会受到太多关注,但仍然要使所有选项完整,这是data.table
library(data.table)
setDT(df)[ , list(mean_gr = mean(dt), sum_gr = sum(dt)) , by = .(group)]
# group mean_gr sum_gr
#1: A 61 244
#2: B 66 396
#3: C 68 408
#4: D 61 488
虽然其他一些方法有效,但这与您正在做的事情非常接近,并且仅使用基本 r。如果您知道聚合命令,这可能更直观。
with( df , aggregate( dt , by=list(group) , FUN=summary) )
评论
该软件包为分组摘要统计信息提供了一个很好的选项:psych
library(psych)
describeBy(dt, group="grp")
生成许多有用的统计数据,包括平均值、中位数、范围、SD、SE。
这也可能起作用,
spl <- split(mtcars, mtcars$cyl)
list.of.summaries <- lapply(spl, function(x) data.frame(apply(x[,3:6], 2, summary)))
list.of.summaries
不知道为什么流行的 skimr
包没有被提出来。它们的函数旨在替换基本 R summary()
并支持分组:skim()
dplyr
library(dplyr)
library(skimr)
starwars %>%
group_by(gender) %>%
skim()
#> ── Data Summary ────────────────────────
#> Values
#> Name Piped data
#> Number of rows 87
#> Number of columns 14
#> _______________________
#> Column type frequency:
#> character 7
#> list 3
#> numeric 3
#> ________________________
#> Group variables gender
#>
#> ── Variable type: character ──────────────────────────────────────────────────────
#> skim_variable gender n_missing complete_rate min max empty n_unique
#> 1 name feminine 0 1 3 18 0 17
#> 2 name masculine 0 1 3 21 0 66
#> 3 name <NA> 0 1 8 14 0 4
#> 4 hair_color feminine 0 1 4 6 0 6
#> 5 hair_color masculine 5 0.924 4 13 0 9
#> 6 hair_color <NA> 0 1 4 7 0 4
#> # [...]
#>
#> ── Variable type: list ───────────────────────────────────────────────────────────
#> skim_variable gender n_missing complete_rate n_unique min_length max_length
#> 1 films feminine 0 1 9 1 5
#> 2 films masculine 0 1 24 1 7
#> 3 films <NA> 0 1 3 1 2
#> 4 vehicles feminine 0 1 3 0 1
#> 5 vehicles masculine 0 1 9 0 2
#> 6 vehicles <NA> 0 1 1 0 0
#> # [...]
#>
#> ── Variable type: numeric ────────────────────────────────────────────────────────
#> skim_variable gender n_missing complete_rate mean sd p0 p25 p50
#> 1 height feminine 1 0.941 165. 23.6 96 162. 166.
#> 2 height masculine 4 0.939 177. 37.6 66 171. 183
#> 3 height <NA> 1 0.75 181. 2.89 178 180. 183
#> # [...]
使用更新的 (>1.0) 版本,您可以使用dplyr
iris %>%
group_by(Species) %>%
summarise(as_tibble(rbind(summary(Sepal.Length))))
这之所以有效,是因为如果参数的计算结果进入数据帧,dplyr 会将结果解压缩到列中。summarise
我还推荐gtsummary(由Daniel D. Sjoberg等人撰写)。您可以使用该包生成可用于发布或演示的表。问题中给出的示例的 gtsummary 解决方案是:
library(tidyverse)
library(gtsummary)
data <- c(62, 60, 63, 59, 63, 67, 71, 64, 65, 66, 68, 66,
71, 67, 68, 68, 56, 62, 60, 61, 63, 64, 63, 59)
grp <- factor(rep(LETTERS[1:4], c(4,6,6,8)))
df <- data.frame(group=grp, dt=data)
tbl_summary(df,
by=group,
type = all_continuous() ~ "continuous2",
statistic = all_continuous() ~ c("{mean} ({sd})","{median} ({IQR})", "{min}- {max}"), ) %>%
add_stat_label(label = dt ~ c("Mean (SD)","Median (Inter Quant. Range)", "Min- Max"))
然后为您提供下面的输出
特征 | A, N = 4 | B, N = 6 | C, N = 6 | D, N = 8 |
---|---|---|---|---|
DT的 | ||||
平均值 (SD) | 61.0 (1.8) | 66.0 (2.8) | 68.0 (1.7) | 61.0 (2.6) |
美安 (IQR) | 61.0 (2.5) | 65.5 (2.5) | 68.0 (0.8) | 61.5 (3.2) |
最小值-最大值 | 59.0 - 63.0 | 63.0 - 71.0 | 66.0 - 71.0 | 56.0 - 64.0 |
您还可以通过执行以下操作将表格导出为 Word 文档:
Table1 <- tbl_summary(df,
by=group,
type = all_continuous() ~ "continuous2",
statistic = all_continuous() ~ c("{mean} ({sd})","{median} ({IQR})", "{min}- {max}"), ) %>%
add_stat_label(label = dt ~ c("Mean (SD)","Median (Inter Quant. Range)", "Min- Max"))
tmp1 <- "~path/name.docx"
Table1 %>%
as_flex_table() %>%
flextable::save_as_docx(path=tmp1)
您也可以将其用于回归输出。有关进一步的见解,请参阅软件包参考手册和软件包网页
https://cran.r-project.org/web/packages/gtsummary/index.html https://www.danieldsjoberg.com/gtsummary/index.html
collapse
提供非常灵活的汇总统计功能:qsu
library(collapse)
with(df, qsu(dt, g = group))
# N Mean SD Min Max
# A 4 61 1.8257 59 63
# B 6 66 2.8284 63 71
# C 6 68 1.6733 66 71
# D 8 61 2.6186 56 64
它的速度也非常快:
microbenchmark::microbenchmark(
tapply = tapply(df$dt, df$group, summary),
dt = setDT(df)[, as.list(summary(dt)), by = group],
collapse = qsu(df$dt, g = df$group),
purrr = df %>% split(.$group) %>% purrr::map(summary)
)
# Unit: microseconds
# expr min lq mean median uq max neval
# tapply 453.2 503.75 531.718 522.70 548.6 946.8 100
# dt 998.8 1076.90 1288.057 1127.55 1205.9 9569.6 100
# collapse 14.8 24.45 38.432 36.90 43.9 121.6 100
# purrr 2553.6 2728.85 2847.378 2816.75 2940.8 3715.8 100
评论
data <- c(