R语言中高效批量合并58对相关列并缩减数据框维度的方法咨询
哈哈,手动写58对列的求和绝对是噩梦!我给你几个高效的解决方案,不管你习惯用tidyverse还是基础R都能轻松搞定:
方法1:用dplyr的across快速批量处理
这个方法最简洁,适合已经在用tidyverse的场景:
library(dplyr) library(stringr) # 先从列名里提取所有的组编号(比如1、2...58) groups <- unique(str_extract(names(DF), "\\d+")) # 批量对每一组的hourX和minutesX求和,自动命名为t1、t2... DF_new <- DF %>% summarise( across(groups, ~ get(paste0("hour", .x)) + get(paste0("minutes", .x)), .names = "t{.x}") )
逻辑解释:
str_extract(names(DF), "\\d+")从列名里提取数字部分,自动获取所有组号across(groups, ...)遍历每个组号,用get()调用对应的hourX和minutesX列,相加后按t{组号}格式命名新列
测试你的示例数据,输出和手动写的完全一致:
DF_new #> t1 t2 #> 1 3.083 4.090 #> 2 2.170 3.180 #> 3 1.250 2.350
方法2:用tidyr的pivot转换(逻辑更直观)
如果对字符串处理不太熟悉,这种“转长-求和-转宽”的方式更容易理解:
library(tidyr) library(dplyr) DF_new <- DF %>% # 添加行号,确保每个样本的信息不丢失 mutate(row_id = row_number()) %>% # 把宽格式转成长格式,拆分列名为「类型(hour/minutes)」和「组号」 pivot_longer(-row_id, names_to = c("type", "group"), names_pattern = "(hour|minutes)(\\d+)") %>% # 按行号+组号分组,求和得到每组的总时间 group_by(row_id, group) %>% summarise(total = sum(value)) %>% # 转回宽格式,命名为t1、t2... pivot_wider(names_from = group, values_from = total, names_prefix = "t") %>% # 去掉临时的行号列 select(-row_id)
逻辑解释:
- 通过
pivot_longer把所有hour和minutes列转成两行(每行对应hour或minutes),同时拆分出组号 - 分组求和后,再用
pivot_wider转回原来的宽格式,得到合并后的列
方法3:基础R实现(无需额外包)
如果不想加载tidyverse包,用基础R也能搞定:
# 提取所有组号 groups <- unique(sub("(hour|minutes)(\\d+)", "\\2", names(DF))) # 批量计算每一组的和,合并成新数据框 DF_new <- do.call(cbind, lapply(groups, function(x) { DF[, paste0("hour", x)] + DF[, paste0("minutes", x)] })) # 设置新列名 colnames(DF_new) <- paste0("t", groups) # 转成数据框格式(可选,默认是矩阵) DF_new <- as.data.frame(DF_new)
逻辑解释:
sub()从列名里替换掉hour/minutes,提取组号lapply()遍历每个组号,计算对应列的和,再用do.call(cbind, ...)把结果合并成矩阵/数据框
这三个方法都能轻松处理58对列,再也不用手动写几十行重复代码啦!
内容的提问来源于stack exchange,提问作者JOHN
相关产品推荐
相关产品推荐

