R语言矩阵去重:基于第一列去重并保留第二列最大值对应行
解决矩阵按第一列去重并保留第二列最大值行的问题
首先,先明确你的核心需求:给定一个矩阵,按第一列的值分组,去除重复分组,只保留每组中第二列值最大的那一行。你之前用duplicated()的方法没得到期望结果,是因为这个函数的逻辑和你的需求不匹配——它只会保留每个第一列值第一次出现的行,而不是第二列最大的行。
先回顾下你的原始数据和期望结果:
原始矩阵
mat <- rbind(c(9,6),c(10,6),c(11,7),c(12,7),c(12,8),c(12,9),c(12,10),c(12,11),c(12,12),c(13,12)) mat
输出:
[,1] [,2] [1,] 9 6 [2,] 10 6 [3,] 11 7 [4,] 12 7 [5,] 12 8 [6,] 12 9 [7,] 12 10 [8,] 12 11 [9,] 12 12 [10,] 13 12
期望结果
[,1] [,2] [1,] 9 6 [2,] 10 6 [3,] 11 7 [4,] 12 12 [5,] 13 12
问题分析
你尝试的代码mat[!duplicated(mat[,1]),],本质是标记第一列中重复出现的元素(从第二次出现开始),然后取反保留第一次出现的行。所以对于第一列=12的组,它保留的是第一次出现的(12,7),而不是你需要的(12,12)。
下面给你两种可行的解决方案:
方案1:Base R 原生实现
不需要额外安装包,用ave()函数就能搞定。ave()可以按分组给每个元素计算对应的值,我们用它标记出每个第一列分组中第二列等于最大值的行:
# 标记每个分组中第二列是最大值的行 max_row_flags <- ave(mat[, 2], mat[, 1], FUN = function(x) x == max(x)) == 1 # 提取符合条件的行 final_result <- mat[max_row_flags, ] # 可选:重置行号(如果需要) rownames(final_result) <- NULL final_result
运行后输出:
[,1] [,2] [1,] 9 6 [2,] 10 6 [3,] 11 7 [4,] 12 12 [5,] 13 12
完美匹配你的期望结果。
方案2:用dplyr包(更易读的 tidyverse 风格)
如果你平时常用tidyverse系列工具,用dplyr的分组筛选逻辑会更直观,代码可读性更高:
library(dplyr) # 把矩阵转成数据框,分组筛选后可转回矩阵 as.data.frame(mat) %>% group_by(V1) %>% # 按第一列(自动命名为V1)分组 filter(V2 == max(V2)) %>% # 保留每组中第二列(V2)最大的行 ungroup() %>% # 取消分组状态 as.matrix() # 可选:转回矩阵格式
这个方法的逻辑和你的需求完全对应:按第一列分组,只留每组第二列最大的行,非常容易理解。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

