【问题标题】:Using `mutate` to create column copies using a named vector使用 `mutate` 使用命名向量创建列副本
【发布时间】:2021-10-27 17:26:39
【问题描述】:

我有一个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 年 8 月 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 创建

【问题讨论】:

    标签: r dplyr names


    【解决方案1】:

    虽然已经有很多答案,但还有一种更重要的方法可以用 {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 年 8 月 28 日创建
    * 感谢 @27 ϕ 9 建议 syms sapply(named_vector, str2lang).

    【讨论】:

    • 不错!完全忘记了我们可以在这里使用syms 来实现预期的行为。我将其添加到我的答案中。
    【解决方案2】:

    另一种选择是在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
    

    【讨论】:

      【解决方案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
      

      【讨论】:

        【解决方案4】:

        您可以使用 -

        从现有列创建新列
        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
        

        【讨论】:

          【解决方案5】:

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

          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来命名向量

          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
          

          更新后的帖子也可以解决问题

          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
          

          【讨论】:

          • 第二个解决方案非常接近,但我发现当列数超过 x1:x3 时它不起作用
          • 我在示例中添加了另外两列,这将导致此错误
          猜你喜欢
          • 2023-04-09
          • 1970-01-01
          • 1970-01-01
          • 2018-08-26
          • 2018-10-03
          • 1970-01-01
          • 1970-01-01
          • 2018-08-13
          • 2023-03-30
          相关资源
          最近更新 更多