【发布时间】:2023-04-09 16:32:02
【问题描述】:
我有一个tibble,我想使用字符向量向它添加列。向量的名称将是新列的名称,新列应填充向量的值(每行重复)。使用 for 循环很容易做到这一点,但我试图了解 across 的工作原理,但遇到了两个问题。
cv <- c("a"="x", "b"="y", "c"="z")
tib <- tibble(c1=1:5)
myf <- function(x) { cv[x]}
tib %>% mutate(across(all_of(names(cv))), myf) ## first problem
# Error: Problem with `mutate()` input `..1`.
# x Can't subset columns that don't exist.
# x Columns `a`, `b`, and `c` don't exist.
tib %>% mutate_at(all_of(names(cv)), myf)
# ℹ Input `..1` is `across(all_of(names(cv)))`.
for (x in names(cv)) { ## do it with a for loop
tib[[x]] <- myf(x)
}
tib %>% mutate(across(all_of(names(cv)), myf)) ## second problem
产生:
# A tibble: 5 x 4
c1 a b c
<int> <chr> <chr> <chr>
1 1 NA NA NA
2 2 NA NA NA
3 3 NA NA NA
4 4 NA NA NA
5 5 NA NA NA
用tib %>% mutate_at(all_of(names(cv)), myf) 替换最后一行会产生同样的错误行为。
第一个问题是mutate across 似乎不喜欢创建新列,原因我无法理解。第二个问题是across 不知道如何处理myf。它似乎想要某种我不知道如何创建的闭包。 (与mutate_at 相同。)我简要地查看了rlang,但无法确定如何将常规函数转换为适当类型的对象。
【问题讨论】:
-
across用于循环已经存在的列 -
@akrun 解释了错误,但它让我不确定
mutate是否可以做到这一点 -
@akrun 我已经更新了问题以反映
mutate_at没有解决任何一个问题 -
mutate_at是mutate和across的前身。行为是循环现有的列。如果您需要创建新列,请使用循环或map