Search code examples
rrlangr-glue

glue and rlang: how to tunnel data-variables within a glue string?


As per this article, a recent version of rlang and glue allows to combine tunnelling {{ myobj }} into a glue string:

library(dplyr)
library(rlang)
library(glue)

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

iris %>% mean_by(Species, Sepal.Width)
#> # A tibble: 3 x 2
#>   Species    avg_Sepal.Width
#>   <fct>                <dbl>
#> 1 setosa                3.43
#> 2 versicolor            2.77
#> 3 virginica             2.97

But if I want to combine on the other side of the equation, I cannot do this:

analyze_by <- function(data, by, var, prefix = "avg") {
  data %>%
    group_by({{ by }}) %>%
    summarise(analysis = glue("{ prefix } by {{ var }}"))
}

iris %>% analyze_by(Species, Sepal.Width)

#> # A tibble: 3 x 2
#>   Species    analysis      
#>   <fct>      <glue>        
#> 1 setosa     avg by { var }
#> 2 versicolor avg by { var }
#> 3 virginica  avg by { var }

What would be the best way to get around this problem?


Solution

  • Perhaps, we can use ensym or enquo before passing into glue

    analyze_by <- function(data, by, var, prefix = "avg") {
     
       var <- rlang::ensym(var)
      
       data %>%
         dplyr::group_by({{ by }}) %>%
         dplyr::summarise(analysis =  glue::glue("{ prefix } by {var}"))
     }
    
    iris %>% 
          analyze_by(Species, Sepal.Width)
    # A tibble: 3 x 2
    #  Species    analysis          
    #  <fct>      <glue>            
    #1 setosa     avg by Sepal.Width
    #2 versicolor avg by Sepal.Width
    #3 virginica  avg by Sepal.Width