clarification on function argument inside dplyr::across

I want to recode some [0,1] variables into factors with levels ["no","yes"] using dplyr::across. I made it work, but I want to understand how to define the function argument inside across in both syntax options.

library(dplyr)
library(forcats)

# toy dataset
df = data.frame(
  var_a = c(0,1,0,1,0,1,0,1,0,1),
  var_b = c(0,1,0,1,0,1,0,1,0,1),
  number_a = 1:10,
  number_b = 21:30)

# selection of columns 
some_cols = c("var_a", "var_b" )


# ---- 1) class transformation
# this works 
df2_a <- df %>% 
  mutate(across(.cols = some_cols, .fns = as.factor, .names = "{.col}_f")) 
# this works too 
df2_b <- df %>% 
  mutate(across(some_cols, ~ as.factor(.x), .names = "{.col}_f")) 


# ---- 2) Change factor levels 
# this DOES NOT work !!!
df3_a <- df2_a %>% 
  mutate(across(.cols = ends_with("_f"), 
                .fns = fct_recode, c(yes = "1", no = "0" ))) 
# this works  
df3_b <- df2_b %>% 
  mutate(across(ends_with("_f"), ~ fct_recode(.x , yes = "1", no = "0" )))

What am I doing wrong in df3_a?

(also asked on stackoverflow here)

Looks like there's a helpful answer there.

A side note is that in their answer, your code

is (implicitly) rewritten as

# this works 
df2_a <- df %>% 
  mutate(across(.cols = all_of(some_cols), .fns = as.factor, .names = "{.col}_f")) 

because of the warning triggered by using the external vector some_cols for the .cols argument. It's a warning now, but in the future we can expect that not using all_of() (or any_of()) will trigger an error instead.

1 Like