7

In the case where a tibble is grouped by multiple variables in dplyr, is there a way to remove a single grouping variable other than re-specifying the groups without that variable? I'm thinking it would be something like group_by(df, -var, add = TRUE), though that doesn't work.

Example:

library(dplyr)

# Works
mtcars %>%
  # Original groups
  group_by(cyl, gear, carb) %>%
  # New groups
  group_by(cyl, gear) %>%
  group_vars() 
# [1] "cyl"  "gear"

# Doesn't work
mtcars %>%
  # Original groups
  group_by(cyl, gear, carb) %>%
  # New groups
  group_by(-carb, add = TRUE) %>%
  group_vars() 
# [1] "cyl"   "gear"  "carb"  "-carb"

This is clearly a trivial example - my actual use case has lots of conditional groupings based on user input and I'd like to just drop one grouping at some point in the function and leave the rest.

MeetMrMet
  • 1,349
  • 8
  • 14
  • 3
    I m not sure this can be done directly from `group_by` or even `ungroup()` (because note that `ungroup(carb)` will not work either). However, you may be able to use `group_by_at()` or `group_by_if()` to handle your case – Sotos Mar 02 '18 at 08:20
  • 2
    Thanks - I'll take a look at those. I think I can save the grouping variables with `group_vars()` and probably pass an edited version of that to `group_by_at()` – MeetMrMet Mar 02 '18 at 08:33
  • That is a good idea – Sotos Mar 02 '18 at 08:35
  • Do you guys know if the `...` arguments of `ungroup` is used at all ? It's not consistent with the relevant help file. – moodymudskipper Mar 02 '18 at 09:36
  • It doesn't seem that way for `ungroup` - I didn't even know `ungroup` had `...` arguments. I've never seen it used with any arguments except the tbl – MeetMrMet Mar 02 '18 at 15:05

3 Answers3

2

You could make a custom function using dplyr::groups or dplyr::group_vars :

ungroup_some <- function(x,...){
  grps <- setdiff(group_vars(x),unlist(list(...)))
  group_by(x,.dots= grps)
}

mtcars %>%
  group_by(cyl, gear, carb) %>%
  ungroup_some("carb")

# # A tibble: 32 x 11
# # Groups:   cyl, gear [8]
#     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#  * <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#  1  21.0     6 160.0   110  3.90 2.620 16.46     0     1     4     4
#  2  21.0     6 160.0   110  3.90 2.875 17.02     0     1     4     4
#  3  22.8     4 108.0    93  3.85 2.320 18.61     1     1     4     1
#  4  21.4     6 258.0   110  3.08 3.215 19.44     1     0     3     1
#  5  18.7     8 360.0   175  3.15 3.440 17.02     0     0     3     2
#  6  18.1     6 225.0   105  2.76 3.460 20.22     1     0     3     1
#  7  14.3     8 360.0   245  3.21 3.570 15.84     0     0     3     4
#  8  24.4     4 146.7    62  3.69 3.190 20.00     1     0     4     2
#  9  22.8     4 140.8    95  3.92 3.150 22.90     1     0     4     2
# 10  19.2     6 167.6   123  3.92 3.440 18.30     1     0     4     4
# # ... with 22 more rows
moodymudskipper
  • 46,417
  • 11
  • 121
  • 167
2

One can use also .dots specification and group by all except some. E.g.

library(dplyr)
ungroup_by <- function(x,...){
  group_by_(x, .dots = group_vars(x)[!group_vars(x) %in% ...])
}

mtcars %>%
  group_by(cyl, gear, carb) %>%
  ungroup_by('cyl') %>%
  group_vars() 
[1] "gear" "carb"

Similar information can be found at this post.

Volodymyr
  • 888
  • 10
  • 21
  • 1
    Great idea. Seems like with `dplyr 0.7` perhaps using `group_by_at` rather than the older SE `group_by_` would be appropriate. – MeetMrMet Mar 02 '18 at 15:02
1

ungroup works directly in dplyr 1.0.8

library(dplyr)
mtcars %>%
  group_by(cyl, gear, carb) %>%
  ungroup(cyl) 
# # A tibble: 32 x 11
# # Groups:   gear, carb [11]
#      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4
#  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4
#  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1
#  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
#  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
#  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
#  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
#  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2
#  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
# 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
user63230
  • 4,095
  • 21
  • 43