MeetMrMet
MeetMrMet

Reputation: 1359

Remove single dplyr group_by group

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.

Upvotes: 8

Views: 6423

Answers (3)

user63230
user63230

Reputation: 4636

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

Upvotes: 3

moodymudskipper
moodymudskipper

Reputation: 47300

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

Upvotes: 2

Volodymyr
Volodymyr

Reputation: 908

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.

Upvotes: 2

Related Questions