Search code examples
rrlangnser-glue

R use bang-bang within a glue statement


I'd like to make a simple function that takes a data frame and user supplied names for two columns in that data frame. The purpose would be to allow this to work easily with dplyr pipes. It will produce a character vector of glued strings:

func <- function(data, last, first) {
  last <- rlang::enquo(last)
  first <- rlang::enquo(first)
  
  glue::glue_data(data, "{!!last}, {!!first}")
}

I'd ideally like a user to be able to call:

df %>% func(lastName, firstName)

This would produce a character vector of multiple values formatted as Smith, John.

My function currently does not work because the bang-bang operators don't work within the context of glue_data. How can I work around this while still using NSE? The error I receive is:

Error: Quosures can only be unquoted within a quasiquotation context.

REPREX:

df <- data.frame(lastName = c("Smith", "Bond", "Trump"), firstName = c("John","James","Donald"))

> df
  lastName firstName
1    Smith      John
2     Bond     James
3    Trump    Donald

EXPECTED OUTPUT

> glue::glue_data(df, "{lastName}, {firstName}")

Smith, John
Bond, James
Trump, Donald

However, I would like to be able to achieve the expected output by using my function and calling:

df %>% func(lastName, firstName)

Above is a simplified version of my actual use case where I will actually be calling the glue statement as a parameter in a follow on function:

biggerfn <- function(data, subject, first, last) {
  subject <- rlang::enquo(subject)
  first <- rlang::enquo(first)
  last <- rlang::enquo(last)
  
  data %>%
    dplyr::distinct(!!subject, !!first, !!last) %>%
    smallerfunc(!!subject, glue::glue_data(data, "{!!last}, {!!first}"))
}

Solution

  • I don't know if you're committed to glue, but this can be easily accomplished using tidyr::unite:

    func <- function(data, last, first) {
        data %>%
            tidyr::unite(result, {{last}}, {{first}}, sep=", ")
    }
    
    df %>% func(lastName, firstName)
    #           result
    #  1   Smith, John
    #  2   Bond, James
    #  3 Trump, Donald
    
    # Optionally, follow up with: 
    #   %>% dplyr::pull(result)
    # to retrieve the column
    

    Here, {{x}} is a shorthand for !!enquo(x).