rgsubacrossmutater-glue

Use substrings of column names in across


I have the following tibble:

df <- tibble(
  x = c(5, 5),
  Column_1 = c(0.5, 0.5),
  Column_2 = c(0.75, 0.75))

I would like to create two new columns, which are the product of column x and Column_1 and x and Column_2 respectively. These columns should be named ABC_1 and ABC_2.

I tried the following code:

df <- mutate(df,
  across(starts_with("Column_"),
              function(y) y * x,
              .names = paste0("ABC", gsub("Column_", "", "{.col}"))
        ))

However, this resulted in the following table:

x Column_1 Column_2 ABCColumn_1 ABCColumn_2
5 0.5 0.75 2.5 3.75
5 0.5 0.75 2.5 3.75

The resulting columns are now named ABCColumn_1 and ABCColumn_2. Somehow creating a substring with gsub did not work. My desired output is:

x Column_1 Column_2 ABC_1 ABC_2
5 0.5 0.75 2.5 3.75
5 0.5 0.75 2.5 3.75

Any ideas how I can elegantly solve this problem? In reality, the number of columns is variable, so I cannot hardcode 1 and 2 into my script.

EDIT: Sorry, my generic columns names were not well chosen. I chose a different one to show that the old and the new column names should not be related in any way except for the number.


Solution

  • The glue strings used in the .names argument of across() evaluate calls so you could do:

    library(dplyr)
    
    df %>%
      mutate(across(starts_with("Column"), ~ x * .x, .names = "ABC_{seq_along(.col)}"))
    
    # A tibble: 2 × 5
          x Column_1 Column_2 ABC_1 ABC_2
      <dbl>    <dbl>    <dbl> <dbl> <dbl>
    1     5      0.5     0.75   2.5  3.75
    2     5      0.5     0.75   2.5  3.75
    

    Or use sub() in the glue string:

    df %>%
      mutate(across(starts_with("Column"), ~ x * .x, .names = "{sub('Column', 'ABC', .col)}"))