如何在R中按分组对矩阵的行和列数值进行求和汇总
R矩阵按行列分组双向求和实现方案
首先先明确核心逻辑:你需要先拆分出原始矩阵的行分组标签、列分组标签和纯数值区域,再按分组交叉求和即可,以下是两种可直接运行的实现:
步骤1:构造原始示例矩阵
a <- matrix(c(NA, NA, "a", "a", "a", "b", "b", NA, NA, 1, 2, 3, 4, 5, "a", 1, 0, 1, 2, 3, 1, "a", 2, 1, 2, 1, 1, 1, "a", 3, 3, 1, 2, 0, 1, "b", 4, 0, 0, 0, 0, 3, "b", 5, 1, 1, 2, 1, 0), ncol = 7, nrow = 7)
实现1:基础R实现(无需安装额外包)
# 1. 提取列分组标签(第一行的有效数据列) col_group <- as.character(a[1, 3:7]) # 2. 提取行分组标签(第一列的有效数据行) row_group <- as.character(a[3:7, 1]) # 3. 提取纯数值矩阵并转换为数值类型 value_mat <- apply(a[3:7, 3:7], 2, as.numeric) # 4. 获取唯一分组名,初始化结果矩阵 groups <- unique(c(row_group, col_group)) res_mat <- matrix(0, nrow = length(groups), ncol = length(groups), dimnames = list(groups, groups)) # 5. 遍历分组交叉求和 for (r in groups) { for (c in groups) { res_mat[r, c] <- sum(value_mat[row_group == r, col_group == c]) } }
运行后得到的res_mat就是你需要的汇总矩阵,验证可知a行a列的求和结果为13,和你给出的示例一致。
实现2:tidyverse实现(适合需要后续链式处理的场景)
如果习惯用tidyverse生态,可以先把矩阵转成长表再聚合,逻辑和aggregate一致:
library(tidyverse) as.data.frame(value_mat) %>% # 绑定行分组标签 mutate(row_group = row_group) %>% # 宽表转长表 pivot_longer(-row_group, names_to = "col_id", values_to = "value") %>% # 绑定列分组标签 mutate(col_group = rep(col_group, each = nrow(value_mat))) %>% # 按行列分组求和 group_by(row_group, col_group) %>% summarise(total = sum(value), .groups = "drop") %>% # 转回宽矩阵格式 pivot_wider(names_from = col_group, values_from = total)
补充说明
你之前用aggregate不成功的核心原因是aggregate默认处理长表结构,你需要先把矩阵中每个数值对应的行、列分组标签匹配上,再传入aggregate即可,上述tidyverse的逻辑也可以直接替换成aggregate实现。
内容的提问来源于stack exchange,提问作者Mir
相关产品推荐
相关产品推荐

