Search code examples
rtidyversedplyrtidyevalacross

tidyverse use across with pasted external vector that contains column names to mutate


Let's assume the following data:

df <- data.frame(x = c(1, 2),
                 y = c(3, 4),
                 z = c(5, 6))

Let's further assume I have a vector that contains column names I want to work on, e.g.

var_names_1 <- c("test", "x", "y")
var_names_2 <- c("test", "z")

Now what I want to do is to mutate all columns of df that are in the var_names_... objects except the first element, using across. (in this case I would do a loop where I go through my both var_names objects).

So in the first loop I want to mutate columns x and y, in the second loop I want to mutate z.

for (i in 1:2)
{
  df %>%
    mutate(across(!!sym(paste0("var_names_", i, [-1])), as_factor))
}

However, I'm getting this error message:

Error: Problem with `mutate()` input `..1`.
x Can't subset columns that don't exist.
x Column `var_names_1` doesn't exist.
i Input `..1` is `across(`var_names_1`, as_factor)`.

I thought I have finally understood some use cases for the tidyeval things, but apparently my !!sym approach doesn't work here. Any suggestions?


Solution

  • Maybe you should try eval + str2expression

    for (i in 1:2){
      str(df %>%
        mutate(across(eval(str2expression(paste0("var_names_", i,"[-1]"))), as_factor)))
    }
    

    which shows

    'data.frame':   2 obs. of  3 variables:
     $ x: num  1 2
     $ y: Factor w/ 2 levels "3","4": 1 2
     $ z: num  5 6
    'data.frame':   2 obs. of  3 variables:
     $ x: num  1 2
     $ y: num  3 4
     $ z: num  5 6