【问题标题】:Split a data frame column containing a list into multiple columns using dplyr (or otherwise)使用 dplyr (或其他方式)将包含列表的数据框列拆分为多列
【发布时间】:2023-04-09 11:16:01
【问题描述】:

考虑以下示例数据

library(dplyr)
tmp <- mtcars %>%
    group_by(cyl) %>%
    summarise(mpg_sum = list(summary(mpg)))

使得mpg_sum 包含mpg 变量在cyl 中的组的最小值、第一个四分位数、中位数、平均值、第三个四分位数和最大值。

如何使用 dplyr 或其他方式将此列解压缩为具有适当列名的 6 列?

【问题讨论】:

  • 你也可以使用library(broom); mtcars %&gt;% group_by(cyl) %&gt;% do(tidy(summary(.$mpg)))
  • 您能否将其发布为答案。我一直对扫帚很感兴趣。
  • 主题变体:mtcars %&gt;% group_by(cyl) %&gt;% summarise(summary = list(broom::tidy(summary(mpg)))) %&gt;% tidyr::unnest()
  • @Alex,我作为答案发布了
  • This answer stackoverflow.com/a/52352912/4269699 to a very similar question解决了这个问题中的具体例子,可能有用。它没有解决将列表列解压缩为多列的更普遍的问题。

标签: r dplyr


【解决方案1】:

我们可以使用data.table。将'data.frame'转换为'data.table'(as.data.table(mtcars)),按'cyl'分组,我们得到'mpg'的summary并转换为list

library(data.table)
as.data.table(mtcars)[, as.list(summary(mpg)), by = cyl]
#    cyl Min. 1st Qu. Median  Mean 3rd Qu. Max.
#1:   6 17.8   18.65   19.7 19.74   21.00 21.4
#2:   4 21.4   22.80   26.0 26.66   30.40 33.9
#3:   8 10.4   14.40   15.2 15.10   16.25 19.2

或者只用dplyr,按照'cyl'分组后,我们用do做和上面一样的操作。

library(dplyr)
mtcars %>%
     group_by(cyl) %>%
     do(data.frame(as.list(summary(.$mpg)), check.names=FALSE) )
#   cyl  Min. 1st Qu. Median  Mean 3rd Qu.  Max.
#  <dbl> <dbl>   <dbl>  <dbl> <dbl>   <dbl> <dbl>
#1     4  21.4   22.80   26.0 26.66   30.40  33.9
#2     6  17.8   18.65   19.7 19.74   21.00  21.4
#3     8  10.4   14.40   15.2 15.10   16.25  19.2

或者使用purrr

library(purrr)
mtcars %>% 
     slice_rows("cyl") %>% 
     select(mpg) %>%
     by_slice(dmap, summary, .collate= "cols")

【讨论】:

  • 这看起来很不错...data.table 的自动命名要好得多,因为您不必指定 check.names
  • 所以dplyr::do 存在问题,因为它删除了除分组列之外的所有列。例如,mtcars %&gt;% group_by(cyl) %&gt;% mutate(mpg_sum = list(summary(mpg)))。如果你解压这个列表,表格的其他列就会消失。
  • 看起来data.table 提供了dplyr 无法提供的解决方案,因为您可以非常轻松地将一个函数调用的多个输出分配给多个命名列。
  • 这是我在 dplyr 中尝试做的事情,但不能:stackoverflow.com/a/38236959/2109289
  • purrr 不再包括by_slice()dmap()。见change log purrr 0.2.2.9000
【解决方案2】:

如评论所述,您还可以使用包broom 中的tidy 函数:

library(broom)
mtcars %>% group_by(cyl) %>% do(tidy(summary(.$mpg)))
# Source: local data frame [3 x 7]
# Groups: cyl [3]
# 
#     cyl minimum    q1 median  mean    q3 maximum
#   (dbl)   (dbl) (dbl)  (dbl) (dbl) (dbl)   (dbl)
# 1     4    21.4 22.80   26.0 26.66 30.40    33.9
# 2     6    17.8 18.65   19.7 19.74 21.00    21.4
# 3     8    10.4 14.40   15.2 15.10 16.25    19.2

【讨论】:

    【解决方案3】:

    (或其他) 选项使用sapply():

    t(sapply(split(mtcars$mpg, mtcars$cyl), summary))
    

    【讨论】:

    • do.call(rbind, by(mtcars$mpg, mtcars$cyl, FUN = summary))
    【解决方案4】:

    另一种选择

    with(data = mtcars,by(mpg,cyl,FUN = summary))
    

    【讨论】:

      猜你喜欢
      • 2019-07-25
      • 2016-10-13
      • 1970-01-01
      • 1970-01-01
      • 2017-08-29
      • 1970-01-01
      • 2022-12-22
      • 1970-01-01
      • 2018-10-31
      相关资源
      最近更新 更多