【问题标题】:How to get summary statistics by group如何按组获取汇总统计信息
【发布时间】:2012-04-08 11:26:23
【问题描述】:

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

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

【问题讨论】:

  • 这是一个非常基本的问题,有多个答案。你可能不熟悉 RSeek (LINK) 和 sos 库 (LINK) 两者都是帮助你找出问题答案的好资源。相信有了这些资源,您将能够在几秒钟内回答您自己的问题。
  • data &lt;- c( 行末尾多了一个逗号。
  • 我刚刚发现了一个很棒的 R 包tables。您可以根据需要将数据按任意多个类别制成表格,并计算多个变量的多个统计数据 - 这真是太棒了!但是等等,还有更多!该软件包具有为您的表格生成 LaTeX 代码的功能,以便轻松导入到您的文档中。

标签: r s


【解决方案1】:

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

【讨论】:

  • @maximusyoda,要获取科学计数法,使用自定义函数代替summary 如:tapply(df$dt, df$group, function(x) format(summary(x), scientific = TRUE))
  • 如何将此列表导出到数据框中?
  • @JorgeParedes,你的意思是汇总统计列表吗?我通常将data.table 包用于这些类型的操作。我会用一个例子来更新答案。
【解决方案2】:

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))

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • df %>% group_by(group) %>% do(data.frame(summary(.))) 应该在 dplyr 中做类似的事情
    • 这似乎产生与使用基本 R 的 tapply 方法相同的输出。
    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

      看看plyr 包。具体来说,ddply

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

      【讨论】:

        【解决方案6】:

        经过 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】:

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

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

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

          【讨论】:

            【解决方案8】:

            除了describeBy,doBy 包是另一种选择。它提供了 SAS PROC Summary 的大部分功能。细节: http://www.statmethods.net/stats/descriptives.html

            【讨论】:

            • 另一种快速制表数据(没有描述性统计数据)的方法是使用descr 包中的freq 函数。严格来说,这不是您所要求的,但可能仍然具有指导意义。详情:rdocumentation.org/packages/descr/functions/freq
            【解决方案9】:

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

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

            【讨论】:

            • 为这个使用base R,返回一个data.frame,并使用summary函数大喊大叫,所以我不需要写一个。
            【解决方案10】:

            不知道为什么 popular skimr package 没有被提出。他们的功能skim()是meant to replace the base 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  
            #> # [...]
            

            【讨论】:

              【解决方案11】:

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

              【讨论】:

                【解决方案12】:

                this 也可以工作,

                spl <- split(mtcars, mtcars$cyl)
                list.of.summaries <- lapply(spl, function(x) data.frame(apply(x[,3:6], 2, summary)))
                list.of.summaries
                

                【讨论】:

                  【解决方案13】:

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

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

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

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2019-03-19
                    • 1970-01-01
                    • 1970-01-01
                    • 2022-11-10
                    • 2021-12-06
                    • 1970-01-01
                    • 2020-12-03
                    相关资源
                    最近更新 更多