tidyverse rename_with 尝试根据现有列值提供新名称时出错

tidyverse rename_with giving error when trying to provide new names based on existing column values

假设数据集如下:

df <- data.frame(...1 = c(1, 2, 3),
                 ...2 = c(1, 2, 3),
                 n_column = c(1, 1, 2))

我现在想重命名所有以“...”开头的变量。我的真实数据集可能有不同数量的“...”变量。关于我有多少这样的变量的信息在 n_column 列中,更准确地说,它是该列的最大值。

所以我尝试了:

df %>%
  rename_with(.cols = starts_with("..."),
              .fn   = paste0("new_name", 1:max(n_column)))

这给出了一个错误:

# Error in paste0("new_name", 1:max(n_column)) : 
#   object 'n_column' not found

所以我猜问题是 paste0 函数确实在当前数据集中查找我提供的列。但是,不确定我该怎么做。有什么想法吗?

我知道我可以通过创建一个包含最大值的外部标量来绕过整个过程。 n_column,但理想情况下,我想在一条管道中完成所有工作。

您不需要来自 n_column 的信息,.cols 将仅传递满足条件 (starts_with("...")) 的列。

library(dplyr)

df %>% rename_with(~paste0("new_name", seq_along(.)),  starts_with("..."))

#  new_name1 new_name2 n_column
#1         1         1        1
#2         2         2        1
#3         3         3        2

这也比使用 max(n_column) 更安全,例如,如果来自 n_column 的数据损坏或列数 ... 发生变化,这仍然有效。


引用 rename_with 中的列值的一种方法是使用匿名函数,这样您就可以使用 .$n_column.

df %>% 
     rename_with(function(x) paste0("new_name", 1:max(.$n_column)),
                 starts_with("..."))

我假设这是较长链的一部分,因此您不想使用 max(df$n_column)

完全不同的方法是

df %>% janitor::clean_names()
  x1 x2 n_column
1  1  1        1
2  2  2        1
3  3  3        2

我们可以使用str_c

library(dplyr)
library(stringr)
df %>% 
    rename_with(~str_c("new_name", seq_along(.)),  starts_with("..."))

或使用base R

i1 <- startsWith(names(df), "...")
names(df)[i1] <- sub("...", "new_name", names(df)[i1], fixed = TRUE)
df
  new_name1 new_name2 n_column
1         1         1        1
2         2         2        1
3         3         3        2