如何让分位数与 summarise_at 和 group_by (dplyr) 一起使用

问题描述 投票:0回答:3

当使用

dplyr
创建按变量级别组织的汇总统计表时,我无法在不重复列名的情况下找出计算四分位数的语法。也就是说,使用调用(例如
vars()
list()
)可以与其他函数(例如
mean()
median()
)一起使用,但不能与
quantile()

一起使用

搜索产生了过时的解决方案,这些解决方案不再有效,因为它们使用已弃用的调用,例如

do()
和/或
funs()

data(iris)
library(tidyverse)

#This works: Notice I have not attempted to calculate quartiles yet
summary_stat <- iris %>% 
  group_by(Species) %>% 
  summarise_at(vars(Sepal.Length), 
               list(min=min, median=median, max=max,
               mean=mean, sd=sd)
               )
A tibble: 3 x 6
  Species      min median   max  mean    sd
  <fct>      <dbl>  <dbl> <dbl> <dbl> <dbl>
1 setosa       4.3    5     5.8  5.01 0.352
2 versicolor   4.9    5.9   7    5.94 0.516
3 virginica    4.9    6.5   7.9  6.59 0.636

##########################################################################
#Does NOT work:
five_number_summary <- iris %>% 
  group_by(Species) %>% 
  summarise_at(vars(Sepal.Length),
               list(min=min, Q1=quantile(.,probs = 0.25),
                    median=median, Q3=quantile(., probs = 0.75),
                    max=max))

Error: Must use a vector in `[`, not an object of class matrix.
Call `rlang::last_error()` to see a backtrace

###########################################################################
#This works: Remove the vars() argument, remove the list() argument,
  #replace summarise_at() with summarise()
  #but the code requires repeating the column name (Sepal.Length)

five_number_summary <- iris %>% 
  group_by(Species) %>% 
  summarise(min=min(Sepal.Length), 
            Q1=quantile(Sepal.Length,probs = 0.25),
            median=median(Sepal.Length), 
            Q3=quantile(Sepal.Length, probs = 0.75),
            max=max(Sepal.Length))

# A tibble: 3 x 6
  Species      min    Q1 median    Q3   max
  <fct>      <dbl> <dbl>  <dbl> <dbl> <dbl>
1 setosa       4.3  4.8     5     5.2   5.8
2 versicolor   4.9  5.6     5.9   6.3   7  
3 virginica    4.9  6.22    6.5   6.9   7.9

最后一段代码产生的正是我正在寻找的内容,但我想知道为什么没有更短的语法不会迫使我重复该变量。

r dplyr quantile
3个回答
12
投票

您在失败的

~
调用中缺少
quantile
函数前面的
summarise_at
。尝试以下操作:

five_number_summary <- iris %>% 
  group_by(Species) %>% 
  summarise_at(vars(Sepal.Length),
               list(min=min, Q1=~quantile(., probs = 0.25),
                    median=median, Q3=~quantile(., probs = 0.75),
                    max=max))
five_number_summary
# A tibble: 3 x 6
  Species      min    Q1 median    Q3   max
  <fct>      <dbl> <dbl>  <dbl> <dbl> <dbl>
1 setosa       4.3  4.8     5     5.2   5.8
2 versicolor   4.9  5.6     5.9   6.3   7  
3 virginica    4.9  6.22    6.5   6.9   7.9

12
投票

您可以在

summarise
内创建数据框/小标题,然后将其拼接成单独的列。

library(tidyverse)

iris %>% 
  group_by(Species) %>% 
  summarise(as_tibble_row(quantile(Sepal.Length)))
#> # A tibble: 3 × 6
#>   Species     `0%` `25%` `50%` `75%` `100%`
#>   <fct>      <dbl> <dbl> <dbl> <dbl>  <dbl>
#> 1 setosa       4.3  4.8    5     5.2    5.8
#> 2 versicolor   4.9  5.6    5.9   6.3    7  
#> 3 virginica    4.9  6.22   6.5   6.9    7.9

# with .name_repair
iris %>% 
  group_by(Species) %>% 
  summarise(as_tibble_row(quantile(Sepal.Length), .name_repair = \(x) paste0('q', parse_number(x))))
#> # A tibble: 3 × 6
#>   Species       q0   q25   q50   q75  q100
#>   <fct>      <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 setosa       4.3  4.8    5     5.2   5.8
#> 2 versicolor   4.9  5.6    5.9   6.3   7  
#> 3 virginica    4.9  6.22   6.5   6.9   7.9

创建于 2023-12-30,使用 reprex v2.0.2

您可以创建一个列表列,然后使用

unnest_wider
,这需要tidyr 1.0.0

library(tidyverse)

iris %>% 
  group_by(Species) %>% 
  summarise(q = list(quantile(Sepal.Length))) %>% 
  unnest_wider(q)

# # A tibble: 3 x 6
#   Species     `0%` `25%` `50%` `75%` `100%`
#   <fct>      <dbl> <dbl> <dbl> <dbl>  <dbl>
# 1 setosa       4.3  4.8    5     5.2    5.8
# 2 versicolor   4.9  5.6    5.9   6.3    7  
# 3 virginica    4.9  6.22   6.5   6.9    7.9

有一个

names_repair
参数,但显然它会更改所有列的名称,而不仅仅是未嵌套的列的名称 (??)

iris %>% 
  group_by(Species) %>% 
  summarise(q = list(quantile(Sepal.Length))) %>% 
  unnest_wider(q, names_repair = ~paste0('Q_', sub('%', '', .)))

# # A tibble: 3 x 6
#   Q_Species    Q_0  Q_25  Q_50  Q_75 Q_100
#   <fct>      <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 setosa       4.3  4.8    5     5.2   5.8
# 2 versicolor   4.9  5.6    5.9   6.3   7  
# 3 virginica    4.9  6.22   6.5   6.9   7.9

另一个选择是

group_modify

iris %>% 
  group_by(Species) %>% 
  group_modify(~as.data.frame(t(quantile(.$Sepal.Length))))

# # A tibble: 3 x 6
# # Groups:   Species [3]
#   Species     `0%` `25%` `50%` `75%` `100%`
#   <fct>      <dbl> <dbl> <dbl> <dbl>  <dbl>
# 1 setosa       4.3  4.8    5     5.2    5.8
# 2 versicolor   4.9  5.6    5.9   6.3    7  
# 3 virginica    4.9  6.22   6.5   6.9    7.9

或者你可以使用 data.table

library(data.table)
irisdt <- as.data.table(iris)

irisdt[, as.list(quantile(Sepal.Length)), Species]
#       Species  0%   25% 50% 75% 100%
# 1:     setosa 4.3 4.800 5.0 5.2  5.8
# 2: versicolor 4.9 5.600 5.9 6.3  7.0
# 3:  virginica 4.9 6.225 6.5 6.9  7.9

3
投票

关于@arienrhod 最新版本的注释

library(dplyr,quietly = TRUE,verbose = FALSE, warn.conflicts = FALSE)
five_number_summary <- iris %>% 
  group_by(Species) %>% 
  summarise(across(Sepal.Length, list(min=min, Q1=~quantile(., probs = 0.25),
                    median=median, Q3=~quantile(., probs = 0.75),
                    max=max),  .names = "{.fn}"))
five_number_summary
#> # A tibble: 3 x 6
#>   Species      min    Q1 median    Q3   max
#>   <fct>      <dbl> <dbl>  <dbl> <dbl> <dbl>
#> 1 setosa       4.3  4.8     5     5.2   5.8
#> 2 versicolor   4.9  5.6     5.9   6.3   7  
#> 3 virginica    4.9  6.22    6.5   6.9   7.9

reprex 包于 2022 年 2 月 21 日创建(v2.0.1)

© www.soinside.com 2019 - 2024. All rights reserved.