使用Dplyr,从字符向量中使用mutate/across添加多列。

4

我想使用dplyr在数据框中添加多列(填充NA)。我已经用一个字符向量定义了这些列的名称。通常,只需添加一列时,可以使用以下模式:

test %>% 
  mutate(!!new_column := NA)

然而,我无法将其与across一起使用:

library(dplyr)

test <- data.frame(a = 1:3)
add_cols <- c("col_1", "col_2")

test %>% 
  mutate(across(!!add_cols, ~ NA))
#> Error: Problem with `mutate()` input `..1`.
#> x Can't subset columns that don't exist.
#> x Columns `col_1` and `col_2` don't exist.
#> ℹ Input `..1` is `across(c("col_1", "col_2"), ~NA)`.

test %>% 
  mutate(!!add_cols := NA)
#> Error: The LHS of `:=` must be a string or a symbol

expected_output <- data.frame(
  a = 1:3,
  col_1 = rep(NA, 3),
  col_2 = rep(NA, 3)
)
expected_output
#>   a col_1 col_2
#> 1 1    NA    NA
#> 2 2    NA    NA
#> 3 3    NA    NA

这段内容是通过reprex包 (v1.0.0)在2021-10-05创建的。

第一种方法正确地创建了列名,但它会直接尝试在现有的列名中查找。第二种方法中,我只能使用单个字符串。

是否有tidyverse解决方案,还是需要使用传统的for循环?

2个回答

6
< p > !! 适用于单个元素

for(nm in add_cols) test <- test %>% 
         mutate(!! nm := NA)

-输出

> test
  a col_1 col_2
1 1    NA    NA
2 2    NA    NA
3 3    NA    NA

另一种选择是:

test %>% 
   bind_cols(setNames(rep(list(NA), length(add_cols)), add_cols))
  a col_1 col_2
1 1    NA    NA
2 2    NA    NA
3 3    NA    NA

基础R语言中,这更容易实现。
test[add_cols] <- NA

可以用于管道中的内容

test %>%
  `[<-`(., add_cols, value = NA)
  a col_1 col_2
1 1    NA    NA
2 2    NA    NA
3 3    NA    NA

across 只有在列已经存在的情况下才能工作,即建议循环遍历数据中存在的列,并使用 .names 修改进行一些修改/创建新的列。


我们可以利用来自 tibbleadd_column

library(tibble)
library(janitor)
add_column(test, !!! add_cols) %>% 
   clean_names %>% 
   mutate(across(all_of(add_cols), ~ NA))
  a col_1 col_2
1 1    NA    NA
2 2    NA    NA
3 3    NA    NA

谢谢你的回答!第二种解决方案看起来很有前途,因为它不会破坏管道。只是想知道是否可以“强制”mutate/across这样做。 - starja
@starja 可以强制执行,但需要在数据中再添加一列。 - akrun
@starja 我添加了几个选项。希望能有所帮助。 - akrun

4

另一种方法:

library(tidyverse)
f <- function(x) df$x = NA
mutate(test, map_dfc(add_cols,~ f(.x)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接