在DataFrame中合并重复列并求和,保留唯一行
合并DataFrame中带.1/.2/.3后缀的重复列并按行求和
问题描述
我原本以为这是个简单任务,但未找到非基于列条件行求和的示例。需求是:将DataFrame中带.1/.2/.3后缀的重复列求和合并,同时保留原唯一行。
输入数据
# 输入DataFrame结构 df <- structure(list(MKC100.1 = c(0L, 1183L, 493L, 43735L, 0L, 59L), MKC100.2 = c(0L, 1666L, 626L, 51511L, 0L, 58L), MKC100.3 = c(0L, 1318L, 543L, 46876L, 0L, 82L), MKC103.1 = c(0L, 0L, 10L, 0L, 2795L, 0L), MKC103.2 = c(0L, 0L, 0L, 0L, 1128L, 0L), MKC103.3 = c(0L, 0L, 0L, 0L, 1956L, 0L), MKC104.2 = c(0L, 10L, 5L, 1L, 1L, 0L), MKC104.3 = c(1L, 20L, 5L, 0L, 1L, 0L )), class = "data.frame", row.names = c("299fc0ac11fb4afd0da849a2c45583b3", "9bc2bacdfadf4c1352ffbc991803287c", "38b782d9f01c69c3570fe0edd5864dc0", "6d078397349f7d39c34d237a6ef4cb75", "c22e752b441ee4190f27a3690c5d1206", "f6513affb198fb9845741b61ece8db4b")) # 输入数据表格展示 # MKC100.1 MKC100.2 MKC100.3 MKC103.1 MKC103.2 MKC103.3 MKC104.2 MKC104.3 # 299fc0ac11fb4afd0da849a2c45583b3 0 0 0 0 0 0 0 1 # 9bc2bacdfadf4c1352ffbc991803287c 1183 1666 1318 0 0 0 10 20 # 38b782d9f01c69c3570fe0edd5864dc0 493 626 543 10 0 0 5 5 # 6d078397349f7d39c34d237a6ef4cb75 43735 51511 46876 0 0 0 1 0 # c22e752b441ee4190f27a3690c5d1206 0 0 0 2795 1128 1956 1 1 # f6513affb198fb9845741b61ece8db4b 59 58 82 0 0 0 0 0
期望输出
# MKC100 MKC103 MKC104 # 299fc0ac11fb4afd0da849a2c45583b3 0 0 1 # 9bc2bacdfadf4c1352ffbc991803287c 4167 0 30 # 38b782d9f01c69c3570fe0edd5864dc0 1662 10 10 # 6d078397349f7d39c34d237a6ef4cb75 142122 0 1 # c22e752b441ee4190f27a3690c5d1206 0 5879 2 # f6513affb198fb9845741b61ece8db4b 199 0 0
补充说明
有时部分重复列会缺失,即便不全仍需合并剩余重复列。
解决方案
方法一:使用tidyverse工具链
通过dplyr和tidyr实现列的转置、分组求和与重塑,兼容缺失列的情况:
library(dplyr) library(tidyr) result <- df %>% rownames_to_column("row_id") %>% # 保留原行名 pivot_longer(-row_id, names_to = "col_name", values_to = "value") %>% # 转长格式 mutate(col_prefix = sub("\\.\\d+$", "", col_name)) %>% # 提取列前缀(移除.1/.2/.3) group_by(row_id, col_prefix) %>% # 按行和前缀分组 summarise(total = sum(value), .groups = "drop") %>% # 组内求和 pivot_wider(names_from = col_prefix, values_from = total) %>% # 转回宽格式 column_to_rownames("row_id") # 恢复原行名 print(result)
方法二:使用Base R
无需额外包,通过字符串处理和循环实现:
# 获取所有唯一的列前缀 prefixes <- unique(sub("\\.\\d+$", "", colnames(df))) # 对每个前缀对应的列按行求和 result_base <- sapply(prefixes, function(p) { # 匹配当前前缀的所有列,drop=FALSE避免单列时转为向量 rowSums(df[, grepl(paste0("^", p, "\\."), colnames(df)), drop = FALSE]) }) # 转换为DataFrame并保留原行名 result_base <- as.data.frame(result_base) rownames(result_base) <- rownames(df) print(result_base)
两种方法均能处理部分重复列缺失的场景,输出结果与期望一致。
内容的提问来源于stack exchange,提问作者Katherine Chau
相关产品推荐
相关产品推荐

