如何从dplyr管道解压缩group_by()do()输出

时间:2018-04-05 02:43:32

标签: r dplyr tidyverse

我有以下代码执行summary() iris$Petal.Width按类别分组

library(tidyverse)
dat <- iris %>% 
  as.tibble() %>% 
  select(Petal.Width, Species) %>% 
  group_by(Species) %>% 
  do(fn = summary(.$Petal.Width))


dat
#> Source: local data frame [3 x 2]
#> Groups: <by row>
#> 
#> # A tibble: 3 x 2
#>   Species    fn                  
#> * <fct>      <list>              
#> 1 setosa     <S3: summaryDefault>
#> 2 versicolor <S3: summaryDefault>
#> 3 virginica  <S3: summaryDefault>

我想要做的是将fn列解压缩到下面(我手动完成)

Species     Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
setosa      0.100   0.200   0.200   0.246   0.300   0.600 
versicolor  1.000   1.200   1.300   1.326   1.500   1.800  
virginica   1.400   1.800   2.000   2.026   2.300   2.500 

我该怎么做?

我试过了,但dat %>% ungroup(fn)

失败了

2 个答案:

答案 0 :(得分:2)

尝试

dat <- iris %>% 
  as.tibble() %>% 
  select(Petal.Width, Species) %>% 
  group_by(Species) %>% 
  do(fn = summary(.$Petal.Width)  %>% as.matrix() %>% t() %>% as.data.frame())

dat %>% unnest()

# # A tibble: 3 x 7
#   Species     Min. `1st Qu.` Median  Mean `3rd Qu.`  Max.
#   <fct>      <dbl>     <dbl>  <dbl> <dbl>     <dbl> <dbl>
# 1 setosa     0.100     0.200  0.200 0.246     0.300 0.600
# 2 versicolor 1.00      1.20   1.30  1.33      1.50  1.80 
# 3 virginica  1.40      1.80   2.00  2.03      2.30  2.50 

答案 1 :(得分:2)

目前,显式列表列首选为do的惯用语。在这种情况下,它可能看起来像

library(tidyverse)

iris %>% 
    group_by(Species) %>% 
    summarise(summary = list(broom::tidy(summary(Petal.Width)))) %>% 
    unnest()
#> # A tibble: 3 x 7
#>   Species    minimum    q1 median  mean    q3 maximum
#>   <fct>        <dbl> <dbl>  <dbl> <dbl> <dbl>   <dbl>
#> 1 setosa       0.100 0.200  0.200 0.246 0.300   0.600
#> 2 versicolor   1.00  1.20   1.30  1.33  1.50    1.80 
#> 3 virginica    1.40  1.80   2.00  2.03  2.30    2.50

如果您愿意,这是基本R习语更简洁和可读的情况之一:

aggregate(Petal.Width ~ Species, iris, summary)
#>      Species Petal.Width.Min. Petal.Width.1st Qu. Petal.Width.Median
#> 1     setosa            0.100               0.200              0.200
#> 2 versicolor            1.000               1.200              1.300
#> 3  virginica            1.400               1.800              2.000
#>   Petal.Width.Mean Petal.Width.3rd Qu. Petal.Width.Max.
#> 1            0.246               0.300            0.600
#> 2            1.326               1.500            1.800
#> 3            2.026               2.300            2.500

但是,请注意,如果您在结果上调用str,则表明Petal.Width实际上是一个矩阵列(在块中是不可能的,但在data.frames中)。要提取它,请点击%>% {cbind(.[1], .[[2]])}或等效。

skimr::skim是另一个尊重dplyr分组的选项:

library(dplyr)

iris %>% group_by(Species) %>% skimr::skim(Petal.Width)
#> Skim summary statistics
#>  n obs: 150 
#>  n variables: 5 
#>  group variables: Species 
#> 
#> Variable type: numeric 
#>     Species    variable missing complete  n mean   sd  p0 p25 p50 p75 p100
#>      setosa Petal.Width       0       50 50 0.25 0.11 0.1 0.2 0.2 0.3  0.6
#>  versicolor Petal.Width       0       50 50 1.33 0.2  1   1.2 1.3 1.5  1.8
#>   virginica Petal.Width       0       50 50 2.03 0.27 1.4 1.8 2   2.3  2.5
#>      hist
#>  ▂▇▁▂▂▁▁▁
#>  ▆▃▇▅▆▂▁▁
#>  ▂▁▇▃▃▆▅▃

它显示的实际上是底层长数据的打印方法。 skimr是为了继续使用dplyr方法而构建的,但在某些时候你可能需要破解底层数据。文档很好地解释了。