You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用dplyr批量重命名数据框中的数字列名?

如何用dplyr批量重命名数据框中的数字列名?

问题背景

现有一个包含纯数字列名的数据框,示例代码如下:

my_df = structure(list(Col1 = c('a', 'b', 'c'), 
                       Col2 = c('d', 'e', 'f'), 
                       `2015` = c('g','h','i'), 
                       `2016` = c('j','k','l'), 
                       `2017` = c('m','n','o'), 
                       `2018` = c('p','q','r'), 
                       `2019` = c('s','t','u'), 
                       `2020` = c('v','w','x'), 
                       `2021` = c('y','z','zz')), 
               row.names = c(NA, -3L), 
               class = c("tbl_df", "tbl", "data.frame"))

需要将所有纯数字列名(如2015)批量重命名为带前缀的字符串(如XYZ_2015),要求使用dplyr管道操作实现自动化,避免手动逐个指定。

现有方案问题

手动逐个重命名的方式繁琐易出错:

new_df = my_df %>%
  rename(XYZ_2015 = `2015`,
         XYZ_2016 = `2016`,
         XYZ_2017 = `2017`,
         XYZ_2018 = `2018`,
         XYZ_2019 = `2019`,
         XYZ_2020 = `2020`,
         XYZ_2021 = `2021`)

尝试for循环自动化时出现报错:

for(year in 2015:2021){
  print(year)
  new_colname = paste0('XYZ_',year)
  my_df = my_df %>% rename(`new_colname` = `year`)
}

报错信息:

Error in `stop_subscript()`:
! Can't rename columns that don't exist.
x Location 2015 doesn't exist.
i There are only 9 columns.
---
Backtrace:
  1. my_df %>% rename(new_colname = year)
  3. dplyr:::rename.data.frame(., new_colname = year)
  4. tidyselect::eval_rename(expr(c(...)), .data)
  5. tidyselect:::rename_impl(...)
  6. tidyselect:::eval_select_impl(...)
 15. tidyselect:::vars_select_eval(...)
 16. tidyselect:::loc_validate(pos, vars, call = error_call)
 17. vctrs::vec_as_location(pos, n = length(vars))
 18. vctrs `<fn>`()
 19. vctrs:::stop_subscript_oob(...)
 20. vctrs:::stop_subscript(...)

错误原因:循环中rename(new_colname=year)的反引号直接引用了字符串字面量,而非变量year和new_colname的实际值,导致dplyr寻找名为year的列而非对应年份的列,同时新列名被固定为new_colname,而非预期的前缀加年份。

解决方案

方法1:使用rename_with()匹配所有纯数字列

dplyr::rename_with()是批量重命名的专用函数,结合正则表达式可自动匹配所有纯数字列:

library(dplyr)

new_df <- my_df %>%
  rename_with(
    # 匹配所有纯数字列名
    .cols = matches("^\\d+$"),
    # 对匹配到的列名添加前缀
    .fn = ~ paste0("XYZ_", .x)
  )
  • matches("^\\d+$"):正则表达式表示匹配从开头到结尾全为数字的列名,自动筛选目标列。
  • .fn = ~ paste0("XYZ_", .x):对每个匹配到的列名.x添加前缀XYZ_。

方法2:精准指定目标年份列

若已知需要重命名的年份范围,可直接指定列名向量,避免误匹配其他纯数字列:

year_cols <- as.character(2015:2021)

new_df <- my_df %>%
  rename_with(
    .cols = all_of(year_cols),
    .fn = ~ paste0("XYZ_", .x)
  )
  • all_of(year_cols):精准匹配向量中指定的列名,确保只处理目标年份列。

方法3:结合命名向量与!!!展开参数

通过创建“新列名=旧列名”的命名向量,再用!!!将其展开为rename()的参数:

year_cols <- as.character(2015:2021)
# 创建命名向量:名字为新列名,值为旧列名
new_names <- setNames(year_cols, paste0("XYZ_", year_cols))

new_df <- my_df %>%
  rename(!!!new_names)
  • !!!:tidyeval语法,将命名向量展开为多个新列名 = 旧列名的参数,传递给rename()。

内容的提问来源于stack exchange,提问作者Felipe D.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 10:01:40