dplyr中的boxplot.stats与组

时间:2019-06-19 14:06:12

标签: r dplyr purrr

我需要计算具有许多组的data.frame的箱线图统计。

我理想地需要的是:

library(dplyr)
iris %>%
  group_by(Species) %>%
  summarise(boxplot=boxplot.stats(Sepal.Length))) # + some kind of magic

# A tibble: 3 x 6
  Species    lower_whisker lower_hinge median upper_hinge upper_whisker
  <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            5.6         6.2    6.5         6.9           7.9

但是到目前为止,我已经完成了一半purrr的映射工作,并且无法解压缩它。

boxplot.stats2 <- function(x, ...) {
  res <- boxplot.stats(x, ...)
  res <- res$stats
  names(res) <- c('lower_whisker','lower_hinge','median','upper_hinge','upper_whisker')
  #t(as.data.frame(res))
  res
}

iris %>%
  group_by(Species) %>%
  summarise(boxplot=list(boxplot.stats2(Sepal.Length)),
    #manual unpacking
    lower_whisker = boxplot[[1]]['lower_whisker'],
    lower_hinge = boxplot[[1]]['lower_hinge'],
    median = boxplot[[1]]['median'],
    upper_hinge = boxplot[[1]]['upper_hinge'],
    upper_whisker = boxplot[[1]]['upper_whisker']
  )

它给出的结果相同,但是我怀疑应该有一个更优雅的解决方案。

1 个答案:

答案 0 :(得分:2)

如果您将列表用作摘要输出,则可以使用软件包 tidyr 中的unnest()函数。

tidyr 的开发版本具有一些新功能,其中包括unnest_wider(),这是适合您情况的便捷工具。

在这里,我将只获得5个箱线图统计数字,并将它们放在summarise()中的列表中,就像您开始做的那样。我也为它们命名,因为boxplot.stats()的统计信息没有任何识别信息。

新列是一个列表列,其中包含每个物种5个值的命名向量。

library(dplyr)
library(tidyr) # development version, tidyr_0.8.3.9000

iris %>%
    group_by(Species) %>%
    summarise(boxplot= list( setNames(boxplot.stats(Sepal.Length)$stats,
                                      c('lower_whisker','lower_hinge','median','upper_hinge','upper_whisker') ) ) )

# A tibble: 3 x 2
  Species    boxplot  
  <fct>      <list>   
1 setosa     <dbl [5]>
2 versicolor <dbl [5]>
3 virginica  <dbl [5]>

紧跟unnest_wider()之后,将为您提供所需的结果。

iris %>%
    group_by(Species) %>%
    summarise(boxplot= list( setNames(boxplot.stats(Sepal.Length)$stats,
                                      c('lower_whisker','lower_hinge','median','upper_hinge','upper_whisker') ) ) ) %>%
    unnest_wider(boxplot)

# A tibble: 3 x 6
  Species    lower_whisker lower_hinge median upper_hinge upper_whisker
  <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            5.6         6.2    6.5         6.9           7.9

您可以跳过命名步骤,但是您需要在末尾命名列。

iris %>%
    group_by(Species) %>%
    summarise(boxplot= list( boxplot.stats(Sepal.Length)$stats ) ) %>%
    unnest_wider(boxplot)

# A tibble: 3 x 6
  Species     ...1  ...2  ...3  ...4  ...5
  <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    5.6   6.2   6.5   6.9   7.9

tidyr 的非开发版本在这里仍然可以提供帮助,尽管这项工作还需要很多步骤。由于列表名称在当前unnest()中丢失,因此您需要在取消嵌套之前手动添加这些名称,以便spread()进入新列。

iris %>%
group_by(Species) %>%
summarise(boxplot= list( boxplot.stats(Sepal.Length)$stats),
          stat = list( c('lower_whisker','lower_hinge','median','upper_hinge','upper_whisker') ) ) %>%
unnest(stat, boxplot) %>%
spread(stat, boxplot)

# A tibble: 3 x 6
  Species    lower_hinge lower_whisker median upper_hinge upper_whisker
  <fct>            <dbl>         <dbl>  <dbl>       <dbl>         <dbl>
1 setosa             4.8           4.3    5           5.2           5.8
2 versicolor         5.6           4.9    5.9         6.3           7  
3 virginica          6.2           5.6    6.5         6.9           7.9