How to use dynamic variables on RHS of dplyr::mutate()?

Viewed 190

Is it possible to use dynamic variables on the RHS of dplyr::mutate()?

Toy example:

temp <- tibble(
  bl = c(1,2,3,4,5),
  fu = c(11,22,33,44,55)
)

bl_var = "bl"
replacement_var = "fu"

# I want a dynamic version of this:
temp %>%
  mutate(bl = fu)

# Something like:
temp %>%
  mutate(!!bl := !!fu)

In my real use case I have a big set of variables measured at baseline, and another set of variables measured at some follow-up period. I don't want to pivot the tibble longer, but want to replace the baseline variables with the follow-up variables.

The variable have a consistent naming scheme:

baseline variables might be: x_1, x_2, x_3, ...

follow-up variable would then be: x_fu_1, x_fu_2, x_fu_3, ...

Thanks to @akrun for the tidy solution. For anyone else with similar scenario, I modified their solution to join updated baseline variables back to original data:

map2_dfc(baseline, followup, ~ temp %>%
  group_by_at(vars(!! row_id)) %>%
    transmute(!! .y := !! rlang::sym(.x))) %>%
right_join(temp, by = row_id)
1 Answers

As it is a string, we can convert to symbol and evaluate (!!) to get the value of the object

library(dplyr)
temp %>%
   mutate(!!bl_var := !! rlang::sym(replacement_var))
# A tibble: 5 x 2
#     bl    fu
#  <dbl> <dbl>
#1    11    11
#2    22    22
#3    33    33
#4    44    44
#5    55    55

If we have multiple variables, create a vector for each of these and then do this with either map or a for loop

library(stringr)
baseline <- str_c("x", 1:3, sep="_")
followup <- str_c("x_fu", 1:3, sep="_")
for(i in seq_along(baseline)) {
     temp <- temp %>%
                mutate(!! followup[i] := !! rlang::sym(baseline[i]) * 5)

    }

Or using map2

library(purrr)
map2_dfc(baseline, followup, ~ temp %>%
                              transmute(!! .y := !! rlang::sym(.x) * 5)) %>%
    bind_cols(temp, .)

There are other options such as _at with transmute_at or mutate_at or mutate/across which can take strings as column names

Related