代码之家  ›  专栏  ›  技术社区  ›  deschen

tidyverse使用粘贴的外部向量,其中包含要更改的列名

  •  0
  • deschen  · 技术社区  · 3 年前

    让我们假设以下数据:

    df <- data.frame(x = c(1, 2),
                     y = c(3, 4),
                     z = c(5, 6))
    

    让我们进一步假设我有一个向量,其中包含我想处理的列名,例如。

    var_names_1 <- c("test", "x", "y")
    var_names_2 <- c("test", "z")
    

    现在我想做的是改变所有列 df 这些都在 var_names_... 除第一个元素之外的对象,使用 across (在这种情况下,我会做一个循环,遍历我的两个var_names对象)。

    所以在第一个循环中,我想改变x和y列,在第二个循环中我想改变z列。

    for (i in 1:2)
    {
      df %>%
        mutate(across(!!sym(paste0("var_names_", i, [-1])), as_factor))
    }
    

    但是,我收到了以下错误消息:

    Error: Problem with `mutate()` input `..1`.
    x Can't subset columns that don't exist.
    x Column `var_names_1` doesn't exist.
    i Input `..1` is `across(`var_names_1`, as_factor)`.
    

    我以为我终于理解了一些琐碎事情的用例,但显然我 !!sym 这种方法在这里行不通。有什么建议吗?

    0 回复  |  直到 3 年前
        1
  •  3
  •   akrun    3 年前

    我们可以使用 any_of 在里面 across

    library(dplyr)
    df1 <- df %>%
        mutate(across(any_of(c(var_names_1, var_names_2)),  factor))
    

    -输出

    str(df1)
    #'data.frame':  2 obs. of  3 variables:
    # $ x: Factor w/ 2 levels "1","2": 1 2
    # $ y: Factor w/ 2 levels "3","4": 1 2
    # $ z: Factor w/ 2 levels "5","6": 1 2 
    

    或者,如果我们需要在循环中传递一个选项 map 会是

    map(list(var_names_1, var_names_2),
            ~ {df <- df %>%
                     mutate(across(any_of(.x), factor))
              })      
    

    或者使用 for

    for(i in 1:2) {
         df <- df %>%
                  mutate(across(any_of(get(str_c("var_names_", i))), factor))
     }
    
        2
  •  1
  •   ThomasIsCoding    3 年前

    也许你应该试试 eval + str2expression

    for (i in 1:2){
      str(df %>%
        mutate(across(eval(str2expression(paste0("var_names_", i,"[-1]"))), as_factor)))
    }
    

    其中显示

    'data.frame':   2 obs. of  3 variables:
     $ x: num  1 2
     $ y: Factor w/ 2 levels "3","4": 1 2
     $ z: num  5 6
    'data.frame':   2 obs. of  3 variables:
     $ x: num  1 2
     $ y: num  3 4
     $ z: num  5 6