【问题标题】:tidyverse use across with pasted external vector that contains column names to mutatetidyverse 与粘贴的外部向量一起使用,其中包含要变异的列名
【发布时间】:2021-05-08 03:11:09
【问题描述】:

让我们假设以下数据:

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")

现在我要做的是使用across 改变var_names_... 对象中除第一个元素之外的所有df 列。 (在这种情况下,我会循环遍历我的两个 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)`.

我以为我终于了解了一些 tidyeval 事物的用例,但显然我的 !!sym 方法在这里不起作用。有什么建议吗?

【问题讨论】:

  • 是否有理由需要循环?为什么不直接使用他们的位置,或者其他整洁的选择选项?
  • 你会先选择然后变异。
  • 这当然是一个简化的例子,在可能的现实生活场景中,我需要将相同的突变应用于我需要动态定义的两个稍微不同的列列表。所以在一种情况下,我想改变例如X1、X2、q、v、z。在第二种情况下,我想对“s1、s2、h、t6”或某事物进行变异。像那样。因此,我无法将任何模式与 tidy select helpers 一起使用。
  • @JuanCamiloRiveraPalacio 好的,这可能是一种解决方法,但是我需要再次加入原始的完整数据框。这里的重点是我还有数百个我想要/需要保留的其他列。

标签: r tidyverse dplyr tidyeval across


【解决方案1】:

我们可以在across中使用any_of

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))
 }

【讨论】:

  • 哇,很高兴知道any_of,它就像一个魅力! +1!
【解决方案2】:

也许你应该试试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

【讨论】:

  • 对不起,这是我上面代码中的一个错字。我实际上使用了 paste0 - 也会在我上面的代码中更新。
  • 我也刚刚意识到它确实适用于我的玩具示例,但如果我的向量中有一个元素我想用 [-1] 排除
  • @deschen 查看我的更新。希望对你有用
  • 很好,工作起来像个魅力。所以我可能需要将此 eval(str2expression) 添加到我的工具箱中。我认为通常的 !!sym 方式可以解决问题。
  • 选择上下文中的正确方法是使用all_of()any_of()。请参阅应被接受为 IMO 答案的其他回复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-12
  • 1970-01-01
  • 2014-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-18
相关资源
最近更新 更多