91

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

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

4

13 回答 13

130

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
于 2012-03-24T10:12:33.690 回答
58

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))
于 2014-11-10T10:59:06.100 回答
39

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

library(purrr)

df %>% split(.$group) %>% map(summary)
于 2016-08-12T14:52:20.130 回答
19

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

describeBy(df$dt, df$group, mat = TRUE) 
于 2012-03-24T05:46:24.437 回答
12

看看plyr包装。具体来说,ddply

ddply(df, .(group), summarise, mean=mean(dt), sum=sum(dt))
于 2012-03-23T22:13:41.767 回答
10

经过 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 
于 2017-01-23T16:53:44.707 回答
7

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

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

产生许多有用的统计数据,包括平均值、中位数、范围、标准差、标准差。

于 2020-03-09T10:50:32.027 回答
6

此外describeBydoBy包装是另一种选择。它提供了 SAS PROC Summary 的大部分功能。详情: http: //www.statmethods.net/stats/descriptives.html

于 2013-12-26T05:04:51.540 回答
5

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

with( df , aggregate( dt , by=list(group) , FUN=summary)  )
于 2019-04-22T12:18:16.300 回答
2

不知道为什么没有提出流行的skimr软件包。它们的功能skim()旨在替换基础 Rsummary()并支持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  
#> # [...]
于 2021-05-10T20:43:02.097 回答
1

首先,这取决于您的 R 版本。如果您已通过 2.11,则可以将聚合门与多个结果函数(摘要、实例或您自己的函数)一起使用。如果没有,您可以使用贾斯汀的答案。

于 2012-03-23T23:40:34.633 回答
1

也可能有效,

spl <- split(mtcars, mtcars$cyl)
list.of.summaries <- lapply(spl, function(x) data.frame(apply(x[,3:6], 2, summary)))
list.of.summaries
于 2021-03-03T08:47:54.913 回答
1

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

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

summarise这是有效的,因为如果参数评估为数据框,dplyr 会将结果解压缩到列中。

于 2021-11-28T18:55:32.690 回答