我注意到这里有很多例子,它们使用dplyr::mutate
和一个返回多个输出的函数来创建多个列。例如:
tmp <- mtcars %>%
group_by(cyl) %>%
summarise(min = summary(mpg)[1],
median = summary(mpg)[3],
mean = summary(mpg)[4],
max = summary(mpg)[6])
然而,这样的语法意味着summary
函数被调用4次,在这个例子中,这似乎不是特别有效。有哪些方法可以有效地将列表输出分配到summarise
或mutate
中的列名列表?
例如,从上一个问题:Split a data frame column containing a list into multiple columns using dplyr (or otherwise),我知道您可以将summary
的输出指定为列表,然后使用do(data.frame(...))
将其拆分,但这意味着您然后必须在以后添加列名,语法不是很漂亮。
答案 0 :(得分:3)
罗曼·弗朗索瓦(Romain Francois)的tie
包裹可以非常巧妙地做到这一点
devtools::install_github("romainfrancois/tie")
library('tidyverse')
library('tie')
tmp <- mtcars %>%
group_by(cyl) %>%
bow( tie(min, median, mean, max) := summary(mpg)[c(1,3,4,6)] )
请注意使用:=
而不是=
。
tidyverse团队在https://github.com/tidyverse/dplyr/issues/154以及其中引用的其他帖子中考虑了在摘要中使用返回向量(不是标量)的函数的问题。
答案 1 :(得分:2)
这解决了你的例子,但也许不是你的主要问题。在您展示的情况下,您可以将其重写为:
tmp <- mtcars %>%
group_by(cyl) %>%
summarise_each(funs(min, median, mean, max), mpg)
效率更高,运行时间约为40%:
microbenchmark(mtcars %>%
group_by(cyl) %>%
summarise_each(funs(min, median, mean, max), mpg),
times = 1000L)
mtcars %>% group_by(cyl) %>% summarise_each(funs(min, median,mean, max), mpg)
min lq mean median uq max neval
2.002762 2.159464 2.330703 2.216719 2.271264 7.771477 1000
microbenchmark(mtcars %>%
group_by(cyl) %>%
summarise(min = summary(mpg)[1],
median = summary(mpg)[3],
mean = summary(mpg)[4],
max = summary(mpg)[6]), times = 1000L)
mtcars %>% group_by(cyl) %>% summarise(min = summary(mpg)[1], median = summary(mpg)[3], mean = summary(mpg)[4], max = summary(mpg)[6])
min lq mean median uq max neval
4.967731 5.21122 5.571605 5.360689 5.530197 13.26596 1000
但是,肯定还有其他情况是否会解决问题。
编辑:
do()
功能可以解决这个问题。 e.g。
by_cyl <- group_by(mtcars, cyl) %>%
do(mod = summary(.)[c(1,4,6),])
答案 2 :(得分:2)
我无法在dplyr
中找到合适的解决方案,让您以易记的方式指定名称。我发现以下data.table
解决方案可以接受,如果有点罗嗦:
data.table(mtcars) %>%
.[, setattr(as.list(summary(mpg)[c(1,3,4,6)]),
"names", c("min", "median", "mean", "max")),
by = cyl]
这源自akrun's answer,其中:
data.table(mtcars) %>%
.[, as.list(summary(mpg)[c(1,3,4,6)]), by = cyl]
自动将函数的输出分配到4列。因此,唯一剩下的就是使用setattr
函数重新命名列。
请注意,summary
的输出不是列表,因此必须强制列表才能使其生效。
答案 3 :(得分:1)
这也可以使用 tidyr::nest
和 purrr::map
来完成。请注意,summary 返回的输出需要从命名向量转换为 data.frame 或 tibble,我在下面使用 dplyr::bind_rows
来完成此操作,但同样可以使用 data.frame(as.list(summary(.$mpg)))
代替。>
suppressWarnings(library(tidyverse))
mtcars %>%
group_by(cyl) %>%
nest() %>%
summarise(stats = map(data, ~ bind_rows(summary(.$mpg)))) %>%
unnest(stats)
#> # A tibble: 3 x 7
#> cyl Min. `1st Qu.` Median Mean `3rd Qu.` Max.
#> <dbl> <table> <table> <table> <table> <table> <table>
#> 1 4 21.4 22.80 26.0 26.66364 30.40 33.9
#> 2 6 17.8 18.65 19.7 19.74286 21.00 21.4
#> 3 8 10.4 14.40 15.2 15.10000 16.25 19.2
由 reprex package (v0.3.0) 于 2021 年 4 月 19 日创建
答案 4 :(得分:0)
我设法这样做了。它使用我拥有的4500万行数据集,工作速度相当快。
{{1}}