rtidyverserlang

Add to curly-curly argument


I am trying to take this canonical example for how the curly-curly operator works

mean_by <- function(data, by, var) {
  data %>%
    dplyr::group_by({{ by }}) %>%
    dplyr::summarise(avg = mean({{ var }}, na.rm = TRUE))
}

mtcars %>% mean_by(by = cyl, var = disp)

and modify it by adding an additional variable to the grouping. Alas, I may never understand what that operator actually does; my attempts to do things like

mean_by <- function(data, by, var) {
  data %>%
    dplyr::group_by({{ c(by, hp) }}) %>%
    dplyr::summarise(avg = mean({{ var }}, na.rm = TRUE))
}

mtcars %>% mean_by(by = cyl, var = disp)

clearly aren't working


Solution

  • A few years ago dplyr added pick to let people pass off {{}} to data masking functions. So you can do something like this.

    library(dplyr)
    
    group_mean = \(data, by, var, ...) {
      data |> 
       group_by(pick({{by}}), ...) |> 
       summarise(mean = mean({{var}}))
    }
    
    group_mean(starwars, by = c(homeworld, species), sex, var = mass)
    #> `summarise()` has grouped output by 'homeworld', 'species'. You can override
    #> using the `.groups` argument.
    #> # A tibble: 64 × 4
    #> # Groups:   homeworld, species [57]
    #>    homeworld      species   sex     mean
    #>    <chr>          <chr>     <chr>  <dbl>
    #>  1 Alderaan       Human     female    49
    #>  2 Alderaan       Human     male      NA
    #>  3 Aleen Minor    Aleena    male      15
    #>  4 Bespin         Human     male      79
    #>  5 Bestine IV     <NA>      <NA>     110
    #>  6 Cato Neimoidia Neimodian male      90
    #>  7 Cerea          Cerean    male      82
    #>  8 Champala       Chagrian  male      NA
    #>  9 Chandrila      Human     female    NA
    #> 10 Concord Dawn   Human     male      79
    #> # ℹ 54 more rows
    

    Created on 2024-09-18 with reprex v2.1.0