dplyr::ungroup() - forget me not. Part 2.

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