使用 `mutate` 使用命名向量创建列副本

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

我有一个 tibble 和一个命名向量。我想在保留原始名称的同时使用矢量名称制作我命名矢量中所有列的 副本

我知道如何相当简单地重命名所有列:

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

reprex package (v0.3.0)

于 2021-08-27 创建

但我不知道如何使用 mutate 做同样的事情。我怎样才能以保留原始名称但也有矢量名称的方式制作列的副本?

我的预期输出相当于:

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

reprex package (v0.3.0)

于 2021-08-27 创建

我们可以将 acrossmutate 一起使用,并通过将子字符串 'x' 替换为 'var' 来使用 str_replace 重命名以创建新列

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

-输出

# 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

或在.names

中使用match到named_vector
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)]}"))

-输出

# 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

使用更新后的 post 解决方案也有效

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

您可以使用 -

从现有列创建新列
data <- tibble::tibble(x1 = 1:3, x2 = 1:3, x3 = 1:3, z = 68, zz = 69)
data[names(named_vector)] <- data[named_vector]
data

#     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

新变量名将从命名向量中获取,只需执行以下操作:

library(dplyr)

tibble(x1 = 1:3, x2 = 4:6, x3 = 7:9, z = 68, zz = 69) %>% 
   mutate(across(all_of(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

另一种选择是在 cbind

之后使用 dplyr 包中的 rename_with
library(dplyr)
df %>% 
    cbind(df[,1:3]) %>% 
    rename_with(.cols = 6:8, ~ names(named_vector), .name_repair = c("minimal"))

输出:

 x1 x2 x3  z zz var1 var2 var3
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

虽然已经有很多答案,但还有一种更重要的方法可以用{dplyr}进行这种编程。 mutate 可以计算表达式列表。因此,我们可以创建一个命名的表达式列表 exp_ls.

,而不是提供 named_vector
library(dplyr)
exp_ls <- list("var1" = expr(x1),
               "var2" = expr(x2),
               "var3" = expr(x3))

tibble(x1 = 1:3, x2 = 1:3, x3 = 1:3, z = 68, zz = 69) %>% 
  mutate(!!! exp_ls)

#> # 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

我们还可以使用 syms(named_vector):*

轻松地将给定的 named_vector 转换为表达式列表
named_vector <- 
  c("var1" = "x1",
    "var2" = "x2",
    "var3" = "x3")

tibble(x1 = 1:3, x2 = 1:3, x3 = 1:3, z = 68, zz = 69) %>% 
  mutate(!!! syms(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

reprex package (v0.3.0)
于 2021-08-28 创建 * 感谢@27 ϕ 9 建议使用 syms 而不是 sapply(named_vector, str2lang).