Home > OS >  Use mutate_at with contains to apply function on multiple columns
Use mutate_at with contains to apply function on multiple columns

Time:05-10

I want to apply a function across multiple columns containing specific strings in their column name. The following has stopped working. Any advice on what is wrong with the code?

Data:

> df=data.frame(ab=1:5, ba=6:10, c=11:15, dc=16:20)
> df
  ab ba  c dc
1  1  6 11 16
2  2  7 12 17
3  3  8 13 18
4  4  9 14 19
5  5 10 15 20

Attempt:

> df %>% dplyr::mutate_at(vars(contains("a"), contains("b")), funs(sqrt(.)))

Error: `.vars` must be a character/numeric vector or a `vars()` object, not a `data.frame` object.
Backtrace:
  9. dplyr::mutate_at(., vars(contains("a"), contains("b")), funs(sqrt(.)))
 10. dplyr:::manip_at(...)
 11. dplyr:::tbl_at_syms(.tbl, .vars, .include_group_vars = .include_group_vars)
 12. dplyr:::tbl_at_vars(tbl, vars, .include_group_vars = .include_group_vars)
 13. dplyr:::bad_args(...)
 14. dplyr:::glubort(fmt_args(args), ..., .envir = .envir)

CodePudding user response:

I would not use mutate_at anymore since it got superseded by the usage of across:

Depending on if you want to perform your function on all columns that contain a AND b or a OR b, you need to change the code below. Currently it has an OR condition.

library(dplyr)
df %>% mutate(across(contains("a") | contains("b"), sqrt))

        ab       ba  c dc
1 1.000000 2.449490 11 16
2 1.414214 2.645751 12 17
3 1.732051 2.828427 13 18
4 2.000000 3.000000 14 19
5 2.236068 3.162278 15 20

CodePudding user response:

Use matches

library(dplyr)
df %>%
   mutate_at(vars(matches('a', 'b')), sqrt)

Or specify the match as a character vector as the documentation says

match - A character vector. If length > 1, the union of the matches is taken.

df %>%
    mutate_at(vars(contains(match = c('a', 'b'))), sqrt)
        ab       ba  c dc
1 1.000000 2.449490 11 16
2 1.414214 2.645751 12 17
3 1.732051 2.828427 13 18
4 2.000000 3.000000 14 19
5 2.236068 3.162278 15 20

_at/_all are deprecated in favor of across

df %>% 
   mutate(across(matches('a', 'b'), sqrt))

-output

        ab       ba  c dc
1 1.000000 2.449490 11 16
2 1.414214 2.645751 12 17
3 1.732051 2.828427 13 18
4 2.000000 3.000000 14 19
5 2.236068 3.162278 15 20
  • Related