如何在R语言中高效交换指定关联列的数值?
R语言高效交换指定后缀列的数值
问题场景
现有如下数据框:
example <- data.frame( date = as.Date(c('2001-01-01', '2001-01-02', '2001-01-01', '2001-01-02')), PID_A = c(1091, 1091, 1037, 1037), PID_B = c(2091, 2091, 2037, 2037), resp_A = c(3,1,2,4), resp_B = c(2,4,3,1), connect_A = c(6,2,5,3), connect_B = c(5,3,6,2), test_A = c(3,9,0,0), test_B = c(1,1,1,1) )
需要交换所有后缀为_A和_B的列数值,但排除PID_A和PID_B,仅处理resp、connect、test这类前缀的列,且实际场景中这类列数量较多,需高效实现。
期望输出:
example_solution <- data.frame( date = as.Date(c('2001-01-01', '2001-01-02', '2001-01-01', '2001-01-02')), PID_A = c(1091, 1091, 1037, 1037), PID_B = c(2091, 2091, 2037, 2037), resp_A = c(2,4,3,1), resp_B = c(3,1,2,4), connect_A = c(5,3,6,2), connect_B = c(6,2,5,3), test_A = c(1,1,1,1), test_B = c(3,9,0,0) )
解决方案
方法1:Base R(无需额外包)
通过提取列前缀、循环交换实现,适合轻量场景:
# 提取所有非PID的_A列前缀 prefixes <- unique(sub("_A$", "", grep("_A$", colnames(example), value = TRUE))) prefixes <- prefixes[prefixes != "PID"] # 循环交换每对_A/_B列 for(p in prefixes) { col_a <- paste0(p, "_A") col_b <- paste0(p, "_B") temp <- example[[col_a]] example[[col_a]] <- example[[col_b]] example[[col_b]] <- temp } # 验证结果是否符合预期 all.equal(example, example_solution) # 返回TRUE
方法2:Tidyverse(dplyr + purrr)
适合整合进复杂数据处理流程,写法更简洁:
library(dplyr) library(purrr) # 先获取需要处理的列前缀 prefixes <- unique(sub("_A$", "", grep("_A$", colnames(example), value = TRUE))) prefixes <- prefixes[prefixes != "PID"] # 构建列名映射(_A对应_B) col_map <- setNames(paste0(prefixes, "_B"), paste0(prefixes, "_A")) # 执行交换 example_swap <- example %>% # 先替换_A列的值为对应_B列的原始值 mutate(across(all_of(names(col_map)), ~ .data[[col_map[cur_column()]]])) %>% # 再替换_B列的值为原始_A列的值 mutate(across(all_of(col_map), ~ example[[names(col_map)[match(cur_column(), col_map)]]])) # 验证结果 all.equal(example_swap, example_solution) # 返回TRUE
说明
- Base R方法无需依赖第三方包,运行高效,适合数据量较大的场景;
- Tidyverse方法代码可读性更强,容易和其他数据清洗步骤结合,适合日常分析流程。
内容的提问来源于stack exchange,提问作者jo_
相关产品推荐
相关产品推荐

