如何按列名数字聚合N×N单位矩阵的行?
按行名列名末尾的数字聚合N×N单位矩阵的行
核心思路
要实现需求,关键在于准确提取行名中的前缀和末尾数字(支持多位数),然后按前缀分组,对指定数字对应的行进行求和合并,同时保留前缀的原始出现顺序。
实现代码
1. 生成示例矩阵
先重现你提供的16×16单位矩阵:
I <- diag(16) names <- paste(rep(c("aaa", "bbb", "ccc", "ddd"), each = 4), rep(1:4, times = 4), sep = "") rownames(I) <- colnames(I) <- names
2. 通用聚合函数
这个函数支持任意N×N矩阵,可自由指定要合并的数字,且能正确识别多位数(如10、22),保留前缀原始顺序:
aggregate_rows_by_suffix_num <- function(mat, target_nums) { # 提取行名中的前缀和末尾数字(支持多位数) name_parts <- strcapture("^(.*?)(\\d+)$", rownames(mat), data.frame(prefix = character(), num = integer())) # 筛选出数字属于目标集合的行 target_idx <- which(name_parts$num %in% target_nums) filtered_mat <- mat[target_idx, , drop = FALSE] filtered_parts <- name_parts[target_idx, ] # 按前缀分组,严格保留前缀的原始出现顺序 unique_prefixes <- unique(filtered_parts$prefix) prefix_groups <- split(seq_len(nrow(filtered_mat)), filtered_parts$prefix)[unique_prefixes] # 对每组行求和,完成合并 agg_rows <- lapply(prefix_groups, function(idx) colSums(filtered_mat[idx, , drop = FALSE])) # 转换为矩阵并设置行名列名 agg_mat <- do.call(rbind, agg_rows) rownames(agg_mat) <- names(agg_rows) colnames(agg_mat) <- colnames(mat) return(agg_mat) }
3. 测试示例
合并数字1和2对应的行:
# 合并数字1、2的行 agg_result <- aggregate_rows_by_suffix_num(I, target_nums = c(1, 2)) # 查看结果 print(agg_result)
4. 测试多位数场景
验证数字大于10的情况(比如10、22):
# 生成包含多位数的测试矩阵 I_large <- diag(6) names_large <- c("ABC1", "ABC10", "DEF2", "DEF22", "GHI3", "GHI33") rownames(I_large) <- colnames(I_large) <- names_large # 合并数字10和22的行 agg_large_result <- aggregate_rows_by_suffix_num(I_large, target_nums = c(10, 22)) print(agg_large_result)
关键细节说明
- 正则表达式
^(.*?)(\\d+)$:用非贪婪匹配.*?提取数字前的所有前缀字符,\\d+匹配一个或多个数字,确保正确识别多位数(不会把"ABC10"拆成"ABC1"和"0")。 - 保留原始顺序:通过
unique(filtered_parts$prefix)获取前缀第一次出现的顺序,避免分组时自动排序,严格遵循原始行名中的前缀顺序。 - 通用性:不依赖第三方包,仅使用R基础函数,适用于任意符合“前缀+末尾数字”格式行名列名的N×N矩阵,支持任意目标数字集合。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

