Search code examples
rdplyrnames

Using `mutate` to create column copies using a named vector


I have a tibble and a named vector. I would like to make copies of all of the columns in my named vector using the vector names while preserving the original names.

I know how to rename all the columns fairly simply:

library(dplyr)

named_vector <- 
  c("var1" = "x1",
    "var2" = "x2",
    "var3" = "x3")

tibble(x1 = 1:3, x2 = 1:3, x3 = 1:3, z = 68, zz = 69) %>% 
  rename(!!!named_vector)
#> # A tibble: 3 x 5
#>    var1  var2  var3     z    zz
#>   <int> <int> <int> <dbl> <dbl>
#> 1     1     1     1    68    69
#> 2     2     2     2    68    69
#> 3     3     3     3    68    69

Created on 2021-08-27 by the reprex package (v0.3.0)

But I don't know how to do the equivalent using mutate. How can I make copies of the columns in a way that preserves the original names and but also has the vector names?

My expected output would be the equivalent of:

library(dplyr)

named_vector <- 
  c("var1" = "x1",
    "var2" = "x2",
    "var3" = "x3")

tibble(x1 = 1:3, x2 = 1:3, x3 = 1:3, z = 68, zz = 69) %>% 
  mutate(var1 = x1,
         var2 = x2,
         var3 = x3)
#> # A tibble: 3 x 8
#>      x1    x2    x3     z    zz  var1  var2  var3
#>   <int> <int> <int> <dbl> <dbl> <int> <int> <int>
#> 1     1     1     1    68    69     1     1     1
#> 2     2     2     2    68    69     2     2     2
#> 3     3     3     3    68    69     3     3     3

Created on 2021-08-27 by the reprex package (v0.3.0)


Solution

  • We may use across with mutate, and rename with str_replace by replacing the substring 'x' with 'var' to create new columns

    library(dplyr)
    library(stringr)
    tibble(x1 = 1:3, x2 = 1:3, x3 = 1:3) %>%
        mutate(across(everything(), 
           .names = "{str_replace(.col, 'x', 'var')}"))
    

    -output

    # A tibble: 3 x 6
         x1    x2    x3  var1  var2  var3
      <int> <int> <int> <int> <int> <int>
    1     1     1     1     1     1     1
    2     2     2     2     2     2     2
    3     3     3     3     3     3     3
    

    Or use match to named_vector in .names

    tibble(x1 = 1:3, x2 = 1:3, x3 = 1:3) %>% 
        mutate(across(all_of(unname(named_vector)),
          .names = "{names(named_vector)[match(.col, named_vector)]}"))
    

    -output

    # A tibble: 3 x 6
         x1    x2    x3  var1  var2  var3
      <int> <int> <int> <int> <int> <int>
    1     1     1     1     1     1     1
    2     2     2     2     2     2     2
    3     3     3     3     3     3     3
    

    With the updated post also the solution works

    tibble(x1 = 1:3, x2 = 1:3, x3 = 1:3, z = 68, zz = 69)  %>%  
        mutate(across(all_of(unname(named_vector)),
           .names = "{names(named_vector)[match(.col, named_vector)]}"))
    # A tibble: 3 x 8
         x1    x2    x3     z    zz  var1  var2  var3
      <int> <int> <int> <dbl> <dbl> <int> <int> <int>
    1     1     1     1    68    69     1     1     1
    2     2     2     2    68    69     2     2     2
    3     3     3     3    68    69     3     3     3