rdplyrr-glue

Apply the glue function to all characted columns of with fields filled from the tibble


I need to allow the users of a function to add new columns with strings created from the values of the supplied tibble. A simple illustration:

df <- data.frame(session=rep(LETTERS[1:3],2),
                 bundle=rep(letters[1:2],3),
                 xn1=sample(1:100,6),
                 xn2=sample(1:100,6))

myfun <- function(df, ...){
  dplyr::mutate(.data=df,!!!rlang::enexprs(...)) |>
    dplyr::mutate(across(where(is.character),~ glue::glue))
}

myfun(df,a=session,b="dsds{session}") 

which if the df is this:

> df
  session bundle xn1 xn2
1       A      a  31  95
2       B      b  45  64
3       C      a  12  38
4       A      b  56  13
5       B      a  70  93
6       C      b  53  73

then I want to get this output if myfun


> myfun(df,a=session,b="dsds{a}")
  session bundle xn1 xn2 a b
1       A      a  31  95 A dsdsA
2       B      b  45  64 B dsdsB 
3       C      a  12  38 C dsdsC
4       A      b  56  13 D dsdsA
5       B      a  70  93 B dsdsB
6       C      b  53  73 C dsdsC
 

But right now I get the errors that glue could not find the session values.

Error in `dplyr::mutate()` at test.R:14:2:
ℹ In argument: `across(where(is.character), ~glue::glue)`.
Caused by error in `across()`:
! Can't compute column `a`.
Caused by error in `dplyr_internal_error()`:
Run `rlang::last_trace()` to see where the error occurred.

Please note that I am not just trying to change the tibble. What I need is to create the myfun() function that would allow the user to create columns in the tibble flexibly.


Solution

  • Is this what you're after? This changes character arguments into glue expressions before splicing everything into mutate():

    library(dplyr)
    library(rlang)
    library(glue)
    
    myfun <- function(.data, ...){
      vars <- exprs(...)
      vars <- lapply(vars, \(x)  if (is.character(x)) expr(glue(!!x)) else x)
      mutate(.data = .data, !!!vars) 
    }
    
    myfun(df, a = session, b = "dsds{a}", a_and_b = "{a} and {b}") 
    
      session bundle xn1 xn2 a     b     a_and_b
    1       A      a  25  61 A dsdsA A and dsdsA
    2       B      b 100  66 B dsdsB B and dsdsB
    3       C      a  86  26 C dsdsC C and dsdsC
    4       A      b  27  33 A dsdsA A and dsdsA
    5       B      a  58  20 B dsdsB B and dsdsB
    6       C      b   7  74 C dsdsC C and dsdsC