简体   繁体   中英

How to use group_by() with an empty argument, in R?

I am writing a function that computes the mean of a variable according to some grouping (g1 and g2). I would like the function to take care of the case when the user just wants to compute the mean across the groups, so the group argument will be empty. I want a solution using tidyverse.

Suppose the following:

y = 1:4
g1 = c('a', 'a', 'b', 'b')
g2 = c(1,2,1,2)
MyData = data.frame(g1, g2, y)

MyFun = function(group){
  group_sym = syms(group)
  MyData %>% 
    group_by(!!!group_sym) %>% 
    summarise(mean = mean(y))
}

# this works well
MyFun(group = c('g1', 'g2'))

Now suppose I want the mean of y across all groups. I would like the function be able to treat something like

MyFun(group = '')

or

MyFun(group = NULL)

So ideally I would like the group argument to be empty / null and thus MyData would not be grouped. One solution could be to add a condition at the beginning of the function checking if the argument is empty and if TRUE write summarise without group_by. But this is not elegant and my real code is much longer than just a few lines.

Any idea?

1) Use {{...}} and use g1 in place of 'g1' :

MyFun = function(group) {
  MyData %>% 
    group_by({{group}}) %>% 
    summarise(mean = mean(y)) %>%
    ungroup
}

MyFun(g1)
## # A tibble: 2 x 2
##   g1     mean
##   <fct> <dbl>
## 1 a       1.5
## 2 b       3.5

MyFun()
## # A tibble: 1 x 1
##    mean
##   <dbl>
## 1   2.5

2) This approach uses 'g1' as in the question.

MyFun = function(group) {
  group <- if (missing(group)) 'All' else sym(group)
  MyData %>% 
    group_by(!!group) %>% 
    summarise(mean = mean(y)) %>%
    ungroup
}

MyFun('g1')
## # A tibble: 2 x 2
##   g1     mean
##   <fct> <dbl>
## 1 a       1.5
## 2 b       3.5

MyFun()
##  # A tibble: 1 x 2
##   `"All"`  mean
##   <chr>   <dbl>
## 1 All       2.5

3) This also works and gives the same output as (2).

MyFun = function(...) {
  group <- if (...length()) syms(...) else 'All'
  MyData %>% 
    group_by(!!!group) %>% 
    summarise(mean = mean(y)) %>%
    ungroup
}
MyFun('g1')
MyFun()

A different approach consists of creating a fake group (named 'across_group') in the data, in the case of group is missing.

MyFun = function(group) {
  if (missing(group)) MyData$across_group = 1
  group <- if (missing(group)) syms('across_group') else syms(group)

  MyData %>% 
    group_by(!!!group) %>% 
    summarise(mean = mean(y)) %>%
    ungroup
}

MyFun()

# A tibble: 1 x 2
  across_group  mean
         <dbl> <dbl>
1            1   2.5

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM