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 “Let’s break backwards compatibility with the universe” non-solution.
Instead of having to use an explicit ungroup()
, use this brand new %>%
(pipe operator)
which will automatically apply an ungroup()
at the end of every chain.
Note: this is a ill-conceived, poorly implemented, fragile, throwaway, non-solution to a complex problem.
But it was fun to do, and that’s what counts! :)
library(magrittr)
library(dplyr)
#-----------------------------------------------------------------------------
# Define a new version of the pipe that always ungroups.
# This is super-fragile, so please do it better!
#-----------------------------------------------------------------------------
'%>%' <- function (lhs, rhs) {
parent <- parent.frame()
env <- new.env(parent = parent)
chain_parts <- magrittr:::split_chain(match.call(), env = env)
pipes <- chain_parts[["pipes"]]
rhss <- chain_parts[["rhss"]]
lhs <- chain_parts[["lhs"]]
env[["_function_list"]] <- lapply(
1:length(rhss),
function(i) magrittr:::wrap_function(rhss[[i]], pipes[[i]], parent)
)
env[["_fseq"]] <- `class<-`(eval(quote(
function(value) freduce(value, `_function_list`)),
env, env), c("fseq", "function")
)
env[["freduce"]] <- freduce
if (magrittr:::is_placeholder(lhs)) {
env[["_fseq"]]
} else {
env[["_lhs"]] <- eval(lhs, parent, parent)
result <- withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
if (magrittr:::is_compound_pipe(pipes[[1L]])) {
eval(call("<-", lhs, result[["value"]]), parent, parent)
} else {
if (result[["visible"]])
ungroup(result[["value"]]) # Explicit 'ungroup()' before returning
else
invisible(ungroup(result[["value"]])) # Explicit ungroup()
}
}
}
#-----------------------------------------------------------------------------
# Use this new pipe instead of the original magrittr pipe
# Note: ungroup() is not called explicitly by the user
#-----------------------------------------------------------------------------
res <- mtcars %>%
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
#-----------------------------------------------------------------------------
# Result is not grouped!
#-----------------------------------------------------------------------------
groups(res)
NULL