如何用dplyr::rename_with重命名非连续列名并调整编号(不依赖列号)
问题
现有以下R代码生成的数据框:
library(tidyverse) dat <- cars %>% t() %>% as_tibble() dat <- dat %>% rename(dummy = V10) dat
输出结果:
# A tibble: 2 × 50 V1 V2 V3 V4 V5 V6 V7 V8 V9 dummy V11 V12 V13 <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 4 4 7 7 8 9 10 10 10 11 11 12 12 2 2 10 4 22 16 10 18 26 34 17 28 14 20 # … with 37 more variables: V14 <dbl>, V15 <dbl>, V16 <dbl>, V17 <dbl>, V18 <dbl>, # V19 <dbl>, V20 <dbl>, V21 <dbl>, V22 <dbl>, V23 <dbl>, V24 <dbl>, V25 <dbl>, # V26 <dbl>, V27 <dbl>, V28 <dbl>, V29 <dbl>, V30 <dbl>, V31 <dbl>, V32 <dbl>, # V33 <dbl>, V34 <dbl>, V35 <dbl>, V36 <dbl>, V37 <dbl>, V38 <dbl>, V39 <dbl>, # V40 <dbl>, V41 <dbl>, V42 <dbl>, V43 <dbl>, V44 <dbl>, V45 <dbl>, V46 <dbl>, # V47 <dbl>, V48 <dbl>, V49 <dbl>, V50 <dbl> # ℹ Use `colnames()` to see all variable names
需要将列名调整为:V1, V2...V9, dummy, V10, V11...,即原V11及之后的列名编号依次减1。要求使用dplyr::rename_with实现,且不依赖列号(实际数据量更大,需处理多组内容)。
解决方案
可以通过rename_with结合正则表达式和条件判断来实现,完全基于列名的模式处理,不依赖列的位置:
dat <- dat %>% rename_with( ~ if_else( # 匹配以V开头且数字大于10的列名 str_detect(., "^V\\d+$") & as.integer(str_remove(., "^V")) > 10, # 捕获数字部分并减1,重新拼接列名 str_replace(., "^V(\\d+)$", function(num) paste0("V", as.integer(num) - 1)), # 不满足条件的列名保持不变 . ) )
工作原理
- 筛选目标列:
str_detect(., "^V\\d+$")匹配所有格式为V+数字的列名,再通过as.integer(str_remove(., "^V")) > 10筛选出数字大于10的列(即原V11及之后的列) - 修改列名:使用正则表达式
^V(\\d+)$捕获列名中的数字部分,将其转为整数后减1,再重新组合成V+新数字的格式 - 保留原列名:非目标列(如
V1-V9、dummy)保持原有名称不变
验证
运行后查看前12列的列名:
colnames(dat) %>% head(12)
输出为:
[1] "V1" "V2" "V3" "V4" "V5" "V6" "V7" "V8" "V9" "dummy" "V10" "V11"
后续列名也会依次递减,完全符合需求。这种方法无需依赖列的位置,可直接应用于大规模数据中的多组同类列名修改场景。
内容的提问来源于stack exchange,提问作者r_noobie
相关产品推荐
相关产品推荐

