Consider the following toy problem.
I would like to round drat
and wt
.
Here is the normal way to do this:
library(tidyverse)
mtcars[1 ,5:7] %>%
mutate(across(.cols = c(drat, wt), .fns = round))
#> drat wt qsec
#> Mazda RX4 4 3 16.46
But what I want to do is select drat
and wt
from the data.
Like below (doesn’t run).
How might I do this?
mtcars_2 <-
mtcars[1 ,5:7] %>%
bind_cols(data.frame(cols_to_modify = "c(drat, wt)"))
## view data
mtcars_2
#> drat wt qsec cols_to_modify
#> Mazda RX4 3.9 2.62 16.46 c(drat, wt)
## my failed attempt
mtcars_2 %>%
mutate(across(.cols = eval(substitute(.$cols)),.fns = round))
#> Error: Problem with `mutate()` input `..1`.
#> ℹ `..1 = across(.cols = eval(substitute(.$cols)), .fns = round)`.
#> x Can't subset columns that don't exist.
#> x Column `c(drat, wt)` doesn't exist.
Created on 2021-10-25 by the reprex package (v2.0.1)
CodePudding user response:
You can't use substitute()
or eval()
on character vectors. You need to parse those character vectors into language objects. Otherwise when you eval a string, you just get that string back. It's not like eval
in other languages. One way to do the parsing is str2lang
. Then you can inject that expression into the across
using tidy evaulation's !!
. For example
mtcars_2 %>%
mutate(across(.cols = !!str2lang(.$cols_to_modify),.fns = round))