如何按组获取汇总统计信息

How to get summary statistics by group

提问人:user1289220 提问时间:3/24/2012 最后编辑:Maëluser1289220 更新时间:8/4/2023 访问量:304932

问:

我正在尝试一次性获得 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)    

我正在寻找的是获取同一组的多个统计数据,例如平均值、最小值、最大值、标准值......等等,这可行吗?

dplyr stat summarize r-faq

评论

2赞 Tyler Rinker 3/24/2012
这是一个非常基本的问题,有多个答案。您可能不熟悉 RSeek (LINK) 和 sos 库 (LINK) 两者都是帮助您找出问题答案的绝佳资源。有了这些资源,您将能够在几秒钟内回答自己的问题。
0赞 BenBarnes 3/24/2012
行尾有一个额外的逗号。data <- c(
0赞 StatGrrl 8/10/2014
我刚刚发现了一个很棒的 R 包。您可以根据需要按任意数量的类别将数据制成表格,并为多个变量计算多个统计数据 - 这真是太棒了!但是等等,还有更多!该软件包具有为您的表格生成 LaTeX 代码的功能,以便轻松导入到您的文档中。

答:

12赞 Justin 3/24/2012 #1

看一下包装。具体说来plyrddply

ddply(df, .(group), summarise, mean=mean(dt), sum=sum(dt))
1赞 CPHM 3/24/2012 #2

首先,这取决于你的 R 版本。如果你已经通过了 2.11,你可以将 aggreggate 与多个结果函数(summary、by instance 或你自己的函数)一起使用。如果没有,您可以使用贾斯汀的答案。

21赞 user666993 3/24/2012 #3

有很多不同的方法可以解决这个问题,但我偏向于包中:describeBypsych

describeBy(df$dt, df$group, mat = TRUE) 
146赞 BenBarnes 3/24/2012 #4

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

评论

4赞 BenBarnes 10/26/2014
@maximusyoda,要获得科学记数法,请使用自定义函数,而不是:summarytapply(df$dt, df$group, function(x) format(summary(x), scientific = TRUE))
0赞 Jorge Paredes 4/6/2021
如何将此列表导出到数据框中?
2赞 BenBarnes 4/19/2021
@JorgeParedes,你是说汇总统计列表吗?我通常将该包用于此类操作。我将用一个例子来更新答案。data.table
6赞 dwstu 12/26/2013 #5

此外,该软件包是另一种选择。它提供了 SAS PROC SUMMARY 的许多功能。细节: http://www.statmethods.net/stats/descriptives.htmldescribeBydoBy

评论

0赞 dwstu 12/26/2013
将数据制成表格(没有描述性统计信息)的另一种快速方法是在包中使用函数。严格来说,这并不是您所要求的,但可能仍然具有指导意义。细节: rdocumentation.org/packages/descr/functions/freqfreqdescr
67赞 Jot eN 11/10/2014 #6

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))
44赞 conor 8/12/2016 #7

使用 Hadley Wickham 的 purrr 包,这非常简单。用于将传递的函数拆分为多个组,然后用于将函数应用于每个组。splitdata_framemapsummary

library(purrr)

df %>% split(.$group) %>% map(summary)

评论

2赞 AlexR 8/12/2016
df %>% group_by(group) %>% do(data.frame(summary(.))) 应该在 dplyr 中做类似的事情
1赞 dsaxton 9/16/2016
这似乎产生了与使用基本 R 的方法相同的输出。tapply
11赞 joel.wilson 1/24/2017 #8

经过漫长的 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 
7赞 MatthewR 4/22/2019 #9

虽然其他一些方法有效,但这与您正在做的事情非常接近,并且仅使用基本 r。如果您知道聚合命令,这可能更直观。

with( df , aggregate( dt , by=list(group) , FUN=summary)  )

评论

1赞 user3055034 2/8/2021
大声喊出这个使用基础 R、返回 data.frame 并使用 summary 函数,所以我不需要写一个。
0赞 Matteo Castagna 5/11/2022
注意:它不返回 data.frame(生成的摘要可视化效果中的每一列都不是 data.frame 名称)。这是一个很好的、高效的、聪明的解决方案。
8赞 FGP 3/9/2020 #10

该软件包为分组摘要统计信息提供了一个很好的选项:psych

library(psych)
    
describeBy(dt, group="grp")

生成许多有用的统计数据,包括平均值、中位数、范围、SD、SE。

1赞 Seyma Kalay 3/3/2021 #11

也可能起作用,

spl <- split(mtcars, mtcars$cyl)
list.of.summaries <- lapply(spl, function(x) data.frame(apply(x[,3:6], 2, summary)))
list.of.summaries
5赞 MS Berends 5/11/2021 #12

不知道为什么流行的 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  
#> # [...]
4赞 Holger Brandl 11/29/2021 #13

使用更新的 (>1.0) 版本,您可以使用dplyr

iris %>% 
  group_by(Species)  %>% 
  summarise(as_tibble(rbind(summary(Sepal.Length))))

这之所以有效,是因为如果参数的计算结果进入数据帧,dplyr 会将结果解压缩到列中。summarise

2赞 Ekow_ababio 3/21/2022 #14

我还推荐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

0赞 Maël 5/5/2023 #15

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