Programmatically dropping a `group_by` field in dplyr

前端 未结 3 1168
挽巷
挽巷 2021-02-20 05:49

I\'m writing functions that take in a data.frame and then do some operations. I need to add and subtract items from the group_by criteria in order to g

3条回答
  •  不知归路
    2021-02-20 06:38

    Here's an approach that uses tidyeval so that bare column names can be used as the function arguments. I'm not sure if it makes sense to convert the bare column names to text (as I've done below) or if there's a more elegant way to work directly with the bare column names.

    drop_groups = function(data, ...) {
    
      groups = map_chr(groups(data), rlang::quo_text)
      drop = map_chr(quos(...), rlang::quo_text)
    
      if(any(!drop %in% groups)) {
        warning(paste("Input data frame is not grouped by the following groups:", 
                      paste(drop[!drop %in% groups], collapse=", ")))
      }
    
      data %>% group_by_at(setdiff(groups, drop))
    
    }
    
    d = mtcars %>% group_by(cyl, vs, am)
    
    groups(d %>% drop_groups(vs, cyl))
    
    [[1]]
    am
    
    groups(d %>% drop_groups(a, vs, b, c))
    
    [[1]]
    cyl
    
    [[2]]
    am
    
    Warning message:
    In drop_groups(., a, vs, b, c) :
      Input data frame is not grouped by the following groups: a, b, c
    

    UPDATE: The approach below works directly with quosured column names, without converting them to strings. I'm not sure which approach is "preferred" in the tidyeval paradigm, or whether there is yet another, more desirable method.

    drop_groups2 = function(data, ...) {
    
      groups = map(groups(data), quo)
      drop = quos(...)
    
      if(any(!drop %in% groups)) {
        warning(paste("Input data frame is not grouped by the following groups:", 
                      paste(drop[!drop %in% groups], collapse=", ")))
      }
    
      data %>% group_by(!!!setdiff(groups, drop))
    
    }
    

提交回复
热议问题