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.
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