dplyr::ungroup() - forget me not

Forget me not - dplyr::ungroup()

If you forget to ungroup() an operation after a group_by() it can lead to unwanted behaviour.

Question: What if we didn’t have to remember to ungroup after every chain?

My post-lunch, sugar-coma non-solution

Instead of using group_by(), use with_group_by() which will automatically apply an ungroup().

This isn’t really a solution as the syntax is pretty darn horrible, but was a fun post-lunch idea to implement.

#-----------------------------------------------------------------------------
#' Perform a grouped operation and automatically ungroup the data
#'
#' @param .data data.frame
#' @param ... arguments.  The last-but-one arguments are treated as
#'        grouping variables. The last argument is treated as a function
#'        chain
#-----------------------------------------------------------------------------
with_group_by <- function(.data, ...) {
  dots   <- rlang::dots_definitions(...)$dots
  f      <- dots[[length(dots)]]
  groups <- dots[-length(dots) ]

  .data <- group_by(.data, !!!groups)
  .data <- rlang::eval_tidy(f)(.data)
  ungroup(.data)
}
#-----------------------------------------------------------------------------
# The first argument is the data frame
# subsequent arguments are the grouping variables
# The final argument to `with_group_by()` treated as a function chain.
#
# Note:  ungroup() is not called explicitly by the user
#-----------------------------------------------------------------------------
res <- mtcars %>%
  with_group_by(
    cyl,
    . %>%
      mutate(mean_mpg = mean(mpg)) %>%
      select(cyl, mean_mpg)
  )
head(res)
# A tibble: 6 x 2
    cyl mean_mpg
  <dbl>    <dbl>
1     6     19.7
2     6     19.7
3     4     26.7
4     6     19.7
5     8     15.1
6     6     19.7
#-----------------------------------------------------------------------------
# Data is not grouped!
#-----------------------------------------------------------------------------
groups(res)
NULL