Suppose you have a dataframe with variables named X1 - X30 and Y1 - Y30. Each of these variables holds integers 1 - 5. We wish to recode some of the variables starting with X like this:
df %<>%
mutate_at(vars(starts_with("X") &
ends_with("5", "8", "16", "22", "28")),
recode, "1" = 5, "2" = 4, "4" = 2, "5" = 1)
This will, however, return the following error:
Error in UseMethod("recode") :
no applicable method for 'recode' applied to an object of class "c('tbl_df', 'tbl', 'data.frame')"
This is because recode needs to take a vector as an argument. So what is the way to bypass this?
mutate_at is entirely designed to take functions that take vectors as an argument, like recode, that is not the issue. Your error is just because you don't use select helpers as logical calls chained with &, instead chain them using , within vars().
Also, if you want what you were aiming for, you would want to use matches to select only columns starting with X and ending with certain numbers.
library(dplyr)
set.seed(123)
df <- data.frame("X1" = sample(1:5, 10, TRUE),
"X2" = sample(1:5, 10, TRUE),
"X3" = sample(1:5, 10, TRUE))
df
#> X1 X2 X3
#> 1 3 5 2
#> 2 3 3 1
#> 3 2 3 3
#> 4 2 1 4
#> 5 3 4 1
#> 6 5 1 3
#> 7 4 1 5
#> 8 1 5 4
#> 9 2 3 2
#> 10 3 2 5
df %>%
mutate_at(vars(matches("^X.*1|2$")),
recode, "1" = 5, "2" = 4, "3" = 3,"4" = 2, "5" = 1)
#> X1 X2 X3
#> 1 3 1 2
#> 2 3 3 1
#> 3 4 3 3
#> 4 4 5 4
#> 5 3 2 1
#> 6 1 5 3
#> 7 2 5 5
#> 8 5 1 4
#> 9 4 3 2
#> 10 3 4 5
Adding a 2021 updated solution including the across function that supersedes the mutate_* functions as well as regex and tidy_select alternatives
library(dplyr)
set.seed(123)
(df <- data.frame("X1" = sample(1:5, 10, TRUE),
"X2" = sample(1:5, 10, TRUE),
"X3" = sample(1:5, 10, TRUE)))
#> X1 X2 X3
#> 1 3 5 2
#> 2 3 3 1
#> 3 2 3 3
#> 4 2 1 4
#> 5 3 4 1
#> 6 5 1 3
#> 7 4 1 5
#> 8 1 5 4
#> 9 2 3 2
#> 10 3 2 5
df %>%
mutate(across(matches("^X.*1|2$"),
recode, "1" = 5, "2" = 4, "3" = 3,"4" = 2, "5" = 1))
#> X1 X2 X3
#> 1 3 1 2
#> 2 3 3 1
#> 3 4 3 3
#> 4 4 5 4
#> 5 3 2 1
#> 6 1 5 3
#> 7 2 5 5
#> 8 5 1 4
#> 9 4 3 2
#> 10 3 4 5
df %>%
mutate(across((starts_with("X") & ends_with(as.character(1:2))),
recode, "1" = 5, "2" = 4, "3" = 3,"4" = 2, "5" = 1))
#> X1 X2 X3
#> 1 3 1 2
#> 2 3 3 1
#> 3 4 3 3
#> 4 4 5 4
#> 5 3 2 1
#> 6 1 5 3
#> 7 2 5 5
#> 8 5 1 4
#> 9 4 3 2
#> 10 3 4 5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With