有条件地将列添加到dplyr R中的groupby

时间:2018-12-21 22:16:25

标签: r dplyr

这里的问题-Select columns in dplyr conditionally-与我的问题有关,但我认为答案并不令人满意。我有以下代码行:

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作为分组变量之一,否则我只想对其他3个变量进行group_by。在没有两个单独的dplyr链的情况下是否可行?一个在if情况下,另一个在else情况下(如上面的链接所述)。我的dplyr链很长,除了group_by之外都是相同的,仅对group_by重复所有代码两次就不干了。

感谢您的帮助!!

2 个答案:

答案 0 :(得分:2)

使用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

答案 1 :(得分:0)

为了使这种缩放比例更好并在仅此一个数据帧之外工作,您可以采用non-standard evaluation / tidyeval方法并编写一个函数,该函数根据某些情况来调整其group_by调用条件参数。这似乎是一个足够普遍的用例,它正在开发一个功能-我已经在为个人/工作包编写的功能中进行了类似的条件分组,并且希望看到{{ 1}}。

以下是*_at_if附带的dplyr数据的示例。在函数mpg中,我要确定2组列:一组将始终用于分组,在ggplot2中作为裸列名称提供,而一组将在以下情况下用于分组: group_conditional是正确的,作为列名称的字符向量提供。

...

您可以在此处看到分组基于提供给condition的简单对/错:

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)
  }
}

显然,您可以使用更复杂的条件。在这里,我仅按条件列分组,如果condition的不同值超过8个(没有,则条件为假):

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…

您的下一步可能是调用mpg$classmpg %>% 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