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