Применить условие суммирования к диапазону столбцов при использовании dplyr group_by? - PullRequest
4 голосов
/ 07 марта 2020

Предположим, мы хотим group_by() и summarise массивный data.frame с очень большим количеством столбцов, но есть несколько больших групп последовательных столбцов, которые будут иметь такое же условие summarise (например, max, mean et c)

Есть ли способ избежать необходимости указывать условие summarise для каждого столбца и вместо этого делать это для диапазонов столбцов ?

Пример

Предположим, что мы хотим сделать это:

iris %>% 
  group_by(Species) %>% 
  summarise(max(Sepal.Length), mean(Sepal.Width), mean(Petal.Length), mean(Petal.Width))

, но учтите, что 3 последовательных столбца имеют одинаковое условие summarise, mean(Sepal.Width), mean(Petal.Length), mean(Petal.Width)

Есть ли способ использовать какой-то метод, например mean(Sepal.Width:Petal.Width), чтобы указать условие для диапазона столбцов, и, следовательно, избежать необходимости многократно вводить условие суммирования для всех столбцов между ними)

Примечание

Приведенный выше пример с радужной оболочкой - это небольшой и управляемый пример, который имеет диапазон из 3 последовательных столбцов, но фактический вариант использования имеет ~ сотни.

Ответы [ 3 ]

5 голосов
/ 07 марта 2020

Следующая версия 1.0.0 из dplyr будет иметь across() функцию, которая делает то, что вам нужно sh для

Basi c использование

across() имеет два основных аргумента:

  • Первый аргумент .cols выбирает столбцы, которые вы хотите работать на. Он использует аккуратный выбор (например, select()), так что вы можете выбирать переменные по позиции, имени и типу.

  • Второй аргумент, .fns, является функцией или списком функций применить к каждому столбцу. Это также может быть формула стиля мурлыкания (или список формул), например ~ .x / 2. (Этот аргумент является необязательным, и вы можете его опустить, если вы просто хотите получить базовые данные; вы увидите, что этот метод используется в vignette("rowwise").)

### Install development version on GitHub first
# install.packages("devtools")
# devtools::install_github("tidyverse/dplyr")
library(dplyr, warn.conflicts = FALSE)

Управление созданием имен с помощью аргумента .names, который принимает клей spe c:

iris %>% 
  group_by(Species) %>% 
  summarise(
    across(c(Sepal.Width:Petal.Width), ~ mean(.x, na.rm = TRUE), .names = "mean_{col}"),
    across(c(Sepal.Length), ~ max(.x, na.rm = TRUE), .names = "max_{col}")
    )
#> # A tibble: 3 x 5
#>   Species    mean_Sepal.Width mean_Petal.Leng~ mean_Petal.Width max_Sepal.Length
#> * <fct>                 <dbl>            <dbl>            <dbl>            <dbl>
#> 1 setosa                 3.43             1.46            0.246              5.8
#> 2 versicolor             2.77             4.26            1.33               7  
#> 3 virginica              2.97             5.55            2.03               7.9

Использование нескольких функций

my_func <- list(
  mean = ~ mean(., na.rm = TRUE),
  max  = ~ max(., na.rm = TRUE)
)

iris %>%
  group_by(Species) %>%
  summarise(across(is.numeric, my_func, .names = "{fn}.{col}"))
#> # A tibble: 3 x 9
#>   Species    mean.Sepal.Length max.Sepal.Length mean.Sepal.Width max.Sepal.Width
#> * <fct>                  <dbl>            <dbl>            <dbl>           <dbl>
#> 1 setosa                  5.01              5.8             3.43             4.4
#> 2 versicolor              5.94              7               2.77             3.4
#> 3 virginica               6.59              7.9             2.97             3.8
#>   mean.Petal.Length max.Petal.Length mean.Petal.Width max.Petal.Width
#> *             <dbl>            <dbl>            <dbl>           <dbl>
#> 1              1.46              1.9            0.246             0.6
#> 2              4.26              5.1            1.33              1.8
#> 3              5.55              6.9            2.03              2.5

Создано в 2020-03-06 пакетом Представ (v0.3.0)

2 голосов
/ 07 марта 2020

Мы можем использовать pmap из purrr, чтобы применять различные функции к различным столбцам, а затем объединять их в конце. Обратите внимание на использование lst из purrr, чтобы мы могли ссылаться на ранее названные объекты в конструкции списка. Это позволяет нам анализировать один и тот же столбец с несколькими функциями, такими как Sepal.Length ниже.

library(tidyverse)

lst(a = list("Sepal.Length", names(select(iris, Sepal.Length:Petal.Width))),
    b = list("max" = max, "mean" = mean),
    c = names(b)) %>%
  pmap(function(a, b, c) {
    iris %>%
      group_by(Species) %>%
      summarize_at(a, b) %>%
      rename_at(a, paste0, "_", c)
  })  %>%
  reduce(inner_join, by = "Species")
#> # A tibble: 3 x 6
#>   Species Sepal.Length_max Sepal.Length_me~ Sepal.Width_mean Petal.Length_me~
#>   <fct>              <dbl>            <dbl>            <dbl>            <dbl>
#> 1 setosa               5.8             5.01             3.43             1.46
#> 2 versic~              7               5.94             2.77             4.26
#> 3 virgin~              7.9             6.59             2.97             5.55
#> # ... with 1 more variable: Petal.Width_mean <dbl>
2 голосов
/ 07 марта 2020

Поскольку summarise сворачивает строки, и, следовательно, мы не можем в дальнейшем применять к нему какие-либо функции, вместо этого мы можем использовать mutate_at, выбрать диапазон столбцов, чтобы применить функцию, а затем выбрать 1-ую строку из каждой группы.

library(dplyr)

iris %>% 
  group_by(Species) %>% 
  mutate_at(vars(Sepal.Width:Petal.Width), mean) %>%
  mutate_at(vars(Sepal.Length), max) %>%
  slice(1L)

#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species   
#         <dbl>       <dbl>        <dbl>       <dbl> <fct>     
#1          5.8        3.43         1.46       0.246 setosa    
#2          7          2.77         4.26       1.33  versicolor
#3          7.9        2.97         5.55       2.03  virginica 
...