How I specify the newly mutated names on mutate(across...) in R

Viewed 585

Within R, when I use mutate across, for the newly created columns, I want to remove a string of text within the existing column name and then put a suffix on the end.

Here is an example:

Dataframe:

d <- data.frame(alpha_rate=1:3, beta_rate=4:6, gamma_rate=7:9)

d
  alpha_rate beta_rate gamma_rate
1          1         4          7
2          2         5          8
3          3         6          9

my_function <- function(x) {(x*8)}

columns_i_want <- c("alpha_rate", "beta_rate")

d <- d %>% mutate(across(all_of(columns_i_want), my_function, .names = "{col}_new"))

The data frame now has the following column names:

  • "alpha_rate", "beta_rate", "gamma_rate", "alpha_rate_new", "beta_rate_new"

Is there a way within the names argument to have these newly created columns to be called this instead (i.e. rate removed, and then the suffix _new):

  • "alpha_rate", "beta_rate", "gamma_rate", "alpha_new", "beta_new"  
2 Answers

You can pass R code in .names -

library(dplyr)

columns_i_want <- c("alpha_rate", "beta_rate")

d %>% mutate(across(all_of(columns_i_want), my_function, 
             .names = "{sub('rate', 'new', col)}"))

#  alpha_rate beta_rate gamma_rate alpha_new beta_new
#1          1         4          7         8       32
#2          2         5          8        16       40
#3          3         6          9        24       48

Not that you asked for it, but here's the neat and fast data.table version:

require(data.table)
require(stringr)
# data
d = data.frame(alpha_rate = 1:3,
               beta_rate = 4:6,
               gamma_rate = 7:9)
setDT(d)
# function
my_function = function(x) {(x*8)}
# code
cols = c("alpha_rate", "beta_rate")
cols_new = str_replace(cols, 'rate', 'new')
d[ , (cols_new) := lapply(.SD, my_function), .SDcols = cols ]
d
Related