如何按组获取摘要统计信息

105

我正在尝试在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)    

我想要的是在一次调用中获取同一组的多个统计数据,例如平均值、最小值、最大值、标准差等,这可行吗?

2
这是一个相当基础的问题,有多个答案。你可能不熟悉RSeek(链接)和sos库(链接)。它们都是非常好的资源,可以帮助你找到答案。我敢打赌,有了这些资源,你能在几秒钟内回答自己的问题。 - Tyler Rinker
data <- c( 行末有多余逗号。 - BenBarnes
我刚刚发现了一个非常棒的 R 包 tables。你可以按照任意多个类别对数据进行表格化,并针对多个变量计算多个统计数据 - 真的非常神奇!但是,还有更多好处!该包还具有用于生成 LaTeX 代码以便于将表格轻松导入文档的功能。 - StatGrrl
15个回答

146

1. tapply

以下是关于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

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
要获得科学计数法,可以使用自定义函数而不是summary,例如:tapply(df$dt, df$group, function(x) format(summary(x), scientific = TRUE)) - BenBarnes
你如何将这个列表导出为数据框? - Jorge Paredes
2
@JorgeParedes,你是指摘要统计信息列表吗?我通常使用data.table包进行这些操作。我会更新答案并提供一个例子。 - BenBarnes

67

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

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

library(purrr)

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

2
df %>% group_by(group) %>% do(data.frame(summary(.))) 在dplyr中应该做类似的事情。 - AlexR
1
这似乎产生了与使用基本R的tapply方法相同的输出。 - dsaxton

21

有很多不同的方法可以解决这个问题,但我比较偏爱 psych 包中的 describeBy 函数:

describeBy(df$dt, df$group, mat = TRUE) 

12

可以看一下 plyr 包。具体地,看一下 ddply

ddply(df, .(group), summarise, mean=mean(dt), sum=sum(dt))

11

经过长达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 

8

psych软件包有一个很好的选项用于分组汇总统计:

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

生成许多有用的统计信息,包括平均值、中位数、范围、标准偏差和标准误差。


7

虽然其他方法也可以使用,但这个方法与您之前所做的相似,并且仅使用基本的r语言功能。如果您熟悉aggregate命令,则可能更易于理解。

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

1
感谢这位使用基本 R、返回 data.frame 并使用 summary 函数的人,让我不必自己编写函数。 - user3055034
注意:它不会返回一个数据框(结果摘要可视化中的每一列都不是数据框名称)。这是一个很好的、高效的、聪明的解决方案。 - Matteo Castagna

6

另一种快速制表数据(不包括描述性统计)的方法是使用descr包中的freq函数。虽然这不完全是您要求的,但仍可能具有指导意义。详情请参见:http://www.rdocumentation.org/packages/descr/functions/freq - dwstu

5

不确定为什么 受欢迎的 skimr 软件包 没有被提及。他们的函数 skim() 旨在 替代基础 R 的 summary(),并支持 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  
#> # [...]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接