Условно добавить столбец в groupby в dplyr R - PullRequest
0 голосов
/ 22 декабря 2018

Этот вопрос здесь - Выбор столбцов в dplyr условно - связан с моим вопросом, но я не считаю ответ удовлетворительным.У меня есть следующая строка кода:

doAGroupBy <- function(data, some_condition) {

  # assume all columns used in filter/group_by are always in data
  new.data <- data %>%
    dplyr::group_by(player, team, game, season) %>%
    dplyr::summarise( ... )

  return(new.data)
}

Мой вопрос такой: я хотел бы добавить game в качестве одной из переменных группировки, когда some_condition == TRUE, в противном случае я хотел бы, чтобы group_by толькодругие 3 переменные.Возможно ли это без двух отдельных цепочек dplyr - одна в случае if, а другая в случае else (как это сделано в ссылке выше).Моя цепочка dplyr длинная и идентична, кроме group_by, и повторение всего кода дважды только для group_by не является СУХИМЫМ.

Спасибо за помощь в этом !!

Ответы [ 2 ]

0 голосов
/ 22 декабря 2018

Для того, чтобы этот масштаб хорошо работал и работал только за один имеющийся у вас фрейм данных, вы можете воспользоваться нестандартной оценкой / tidyeval и написать функцию, которая корректирует вызов group_byоснованный на некотором аргументе условия.Это похоже на достаточно распространенный вариант использования, когда он работает над разработкой функции - я выполнил аналогичную условную группировку в функциях, которые я написал для личного / рабочего пакета, и хотел бы видеть похожие *_at_if функции, принятые в dplyr.

Вот пример с данными mpg, которые поставляются с ggplot2.В функции group_conditional я создаю кавычки из 2 наборов столбцов: один, который всегда будет использоваться для группировки, предоставляется как пустые имена столбцов в ..., и один, который будет использоваться для группировки, если conditionЗначение true, предоставляется как символьный вектор имен столбцов.

library(tidyverse)

group_conditional <- function(.data, ..., conditional_cols, condition) {
  base_group_vars <- quos(...)
  conditional_group_vars <- syms(conditional_cols)
  if (condition) {
    .data %>%
      group_by(!!!base_group_vars, !!!conditional_group_vars)
  } else {
    .data %>%
      group_by(!!!base_group_vars)
  }
}

Здесь вы можете видеть, что группировка основана на простом значении true / false, предоставленном condition:

mpg %>%
  group_conditional(manufacturer, year, 
                    conditional_cols = c("class", "trans"), 
                    condition = T) %>%
  head()
#> # A tibble: 6 x 11
#> # Groups:   manufacturer, year, class, trans [4]
#>   manufacturer model displ  year   cyl trans  drv     cty   hwy fl    class
#>   <chr>        <chr> <dbl> <int> <int> <chr>  <chr> <int> <int> <chr> <chr>
#> 1 audi         a4      1.8  1999     4 auto(… f        18    29 p     comp…
#> 2 audi         a4      1.8  1999     4 manua… f        21    29 p     comp…
#> 3 audi         a4      2    2008     4 manua… f        20    31 p     comp…
#> 4 audi         a4      2    2008     4 auto(… f        21    30 p     comp…
#> 5 audi         a4      2.8  1999     6 auto(… f        16    26 p     comp…
#> 6 audi         a4      2.8  1999     6 manua… f        18    26 p     comp…

mpg %>%
  group_conditional(manufacturer, year, 
                    conditional_cols = c("class", "trans"), 
                    condition = F) %>%
  head()
#> # A tibble: 6 x 11
#> # Groups:   manufacturer, year [2]
#>   manufacturer model displ  year   cyl trans  drv     cty   hwy fl    class
#>   <chr>        <chr> <dbl> <int> <int> <chr>  <chr> <int> <int> <chr> <chr>
#> 1 audi         a4      1.8  1999     4 auto(… f        18    29 p     comp…
#> 2 audi         a4      1.8  1999     4 manua… f        21    29 p     comp…
#> 3 audi         a4      2    2008     4 manua… f        20    31 p     comp…
#> 4 audi         a4      2    2008     4 auto(… f        21    30 p     comp…
#> 5 audi         a4      2.8  1999     6 auto(… f        16    26 p     comp…
#> 6 audi         a4      2.8  1999     6 manua… f        18    26 p     comp…

Очевидно,Вы можете использовать более сложные условия.Здесь я группирую только по условным столбцам, если имеется более 8 различных значений mpg$class (нет, поэтому условие ложно):

mpg %>%
  group_conditional(manufacturer, year, 
                    conditional_cols = c("class", "trans"), 
                    condition = n_distinct(mpg$class) > 8) %>%
  head()
#> # A tibble: 6 x 11
#> # Groups:   manufacturer, year [2]
#>   manufacturer model displ  year   cyl trans  drv     cty   hwy fl    class
#>   <chr>        <chr> <dbl> <int> <int> <chr>  <chr> <int> <int> <chr> <chr>
#> 1 audi         a4      1.8  1999     4 auto(… f        18    29 p     comp…
#> 2 audi         a4      1.8  1999     4 manua… f        21    29 p     comp…
#> 3 audi         a4      2    2008     4 manua… f        20    31 p     comp…
#> 4 audi         a4      2    2008     4 auto(… f        21    30 p     comp…
#> 5 audi         a4      2.8  1999     6 auto(… f        16    26 p     comp…
#> 6 audi         a4      2.8  1999     6 manua… f        18    26 p     comp…

Ваш следующий шаг может бытьпозвоните на summarise_all, summarise_if или что-то подобное:

mpg %>%
  group_conditional(manufacturer, year, 
                    conditional_cols = c("class", "trans"), 
                    condition = T) %>%
  summarise_if(is.numeric, mean) %>%
  head()
#> # A tibble: 6 x 8
#> # Groups:   manufacturer, year, class [3]
#>   manufacturer  year class   trans      displ   cyl   cty   hwy
#>   <chr>        <int> <chr>   <chr>      <dbl> <dbl> <dbl> <dbl>
#> 1 audi          1999 compact auto(l5)    2.3   5     16.2  26.2
#> 2 audi          1999 compact manual(m5)  2.3   5     18.5  26.5
#> 3 audi          1999 midsize auto(l5)    2.8   6     15    24  
#> 4 audi          2008 compact auto(av)    2.55  5     19.5  28.5
#> 5 audi          2008 compact auto(s6)    2.55  5     18    26  
#> 6 audi          2008 compact manual(m6)  2.37  4.67  18.3  28
0 голосов
/ 22 декабря 2018

Используя mtcars для примера игрушки и group_by_at для решения вашей проблемы.

library(tidyverse)

doAGroupBy <- function(data, some_condition) {

  if (some_condition == TRUE) {

    group_args <- c("cyl","carb","disp","hp")

  } else {

    group_args <-  c("cyl","carb","disp")

  }

  data %>%
    dplyr::group_by_at(group_args) %>%
    dplyr::summarise(mpg = mean(mpg))
}

doAGroupBy(mtcars, FALSE)
#> # A tibble: 28 x 4
#> # Groups:   cyl, carb [?]
#>      cyl  carb  disp   mpg
#>    <dbl> <dbl> <dbl> <dbl>
#>  1     4     1  71.1  33.9
#>  2     4     1  78.7  32.4
#>  3     4     1  79    27.3
#>  4     4     1 108    22.8
#>  5     4     1 120.   21.5
#>  6     4     2  75.7  30.4
#>  7     4     2  95.1  30.4
#>  8     4     2 120.   26  
#>  9     4     2 121    21.4
#> 10     4     2 141.   22.8
#> # ... with 18 more rows

doAGroupBy(mtcars, TRUE)
#> # A tibble: 28 x 5
#> # Groups:   cyl, carb, disp [?]
#>      cyl  carb  disp    hp   mpg
#>    <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1     4     1  71.1    65  33.9
#>  2     4     1  78.7    66  32.4
#>  3     4     1  79      66  27.3
#>  4     4     1 108      93  22.8
#>  5     4     1 120.     97  21.5
#>  6     4     2  75.7    52  30.4
#>  7     4     2  95.1   113  30.4
#>  8     4     2 120.     91  26  
#>  9     4     2 121     109  21.4
#> 10     4     2 141.     95  22.8
#> # ... with 18 more rows
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...