如何移除数据框变量名中除最后一个下划线外的所有下划线?
移除数据框变量名中除最后一个下划线外的所有下划线
需求说明
需要移除数据框变量名中除最后一个实例外的所有下划线(_),且不依赖最后一个下划线后的字符模式,确保代码能适配所有含多个下划线的变量名。
示例数据
原数据框结构:
structure(list(subjectID = c("P1", "P2", "P3", "P4", "P5"), var_t1_new_3m = c(1, 3, 5, 2, 1), var_t1_old_3m = c(6, 8, 9, 2, 3), var_t2_new_6m = c(1, 5, 8, 9, 3), var_t2_old_6m = c(5, 3, 8, 1, 7), var_t3_new_12m = c(1, 9, 2, 7, 3), var_t3_old_12m = c(6, 1, 4, 9, 3)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -5L))
期望处理后的变量名结构:
structure(list(subjectID = c("P1", "P2", "P3", "P4", "P5"), vart1new_3m = c(1, 3, 5, 2, 1), vart1old_3m = c(6, 8, 9, 2, 3), vart2new_6m = c(1, 5, 8, 9, 3), vart2old_6m = c(5, 3, 8, 1, 7), var3new_12m = c(1, 9, 2, 7, 3), var3old_12m = c(6, 1, 4, 9, 3)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -5L))
过往尝试的问题
曾尝试用str_replace_all结合正向预查的方式处理,但因依赖_[:digit:]m的固定模式,导致下划线后是多位数的变量名(如age_eeg_12m)处理失效,无法适配所有场景。
解决方案
方法1:基于正则替换的简洁实现
使用stringr包的str_replace_all,通过正则匹配后面仍存在下划线的所有下划线,直接替换为空:
library(stringr) library(dplyr) # 加载示例数据 df <- structure(list(subjectID = c("P1", "P2", "P3", "P4", "P5"), var_t1_new_3m = c(1, 3, 5, 2, 1), var_t1_old_3m = c(6, 8, 9, 2, 3), var_t2_new_6m = c(1, 5, 8, 9, 3), var_t2_old_6m = c(5, 3, 8, 1, 7), var_t3_new_12m = c(1, 9, 2, 7, 3), var_t3_old_12m = c(6, 1, 4, 9, 3)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -5L)) # 处理变量名 names(df) <- str_replace_all(names(df), "_+(?=.*_)", "") # 查看处理结果 print(df)
正则说明:_+(?=.*_)中,_+匹配一个或多个下划线,(?=.*_)是正向预查,确保当前匹配的下划线后面还有至少一个下划线,这样就只会替换最后一个下划线之前的所有下划线。
方法2:分割拼接法(更直观)
将变量名按最后一个下划线分割为两部分,移除前半部分的所有下划线后,再与后半部分拼接:
library(stringr) library(dplyr) # 处理变量名 names(df) <- str_split_fixed(names(df), "_(?!.*_)", 2) %>% apply(1, function(x) { # 前半部分去掉所有下划线 part1 <- str_remove_all(x[1], "_") # 后半部分非空则保留下划线拼接,否则直接用前半部分 if (nchar(x[2]) > 0) paste0(part1, "_", x[2]) else part1 })
正则说明:_(?!.*_)是负向预查,匹配最后一个下划线,确保分割后的后半部分是最后一个下划线之后的内容。
两种方法都能适配所有含多个下划线的变量名,且不依赖最后下划线后的字符模式,同时对只有单个下划线或无下划线的变量名(如subjectID)也能正常保留。
内容的提问来源于stack exchange,提问作者mr1890
相关产品推荐
相关产品推荐

