在R语言中忽略列顺序去除重复行的最优方案
问题描述
原始对称矩阵:
| a | b | c | |
|---|---|---|---|
| a | 0 | 0.576 | 0.987 |
| b | 0.576 | 0 | 0.034 |
| c | 0.987 | 0.034 | 0 |
经melt转换为长格式并移除自身映射的零值后的数据:
| var1 | var2 | value |
|---|---|---|
| a | b | 0.576 |
| b | a | 0.576 |
| a | c | 0.987 |
| c | a | 0.987 |
| b | c | 0.034 |
| c | b | 0.034 |
需要去除对称重复行(如(a,b)与(b,a)视为重复),得到如下结果:
| var1 | var2 | value |
|---|---|---|
| a | b | 0.576 |
| a | c | 0.987 |
| b | c | 0.034 |
解决方案
方法一:Python Pandas 实现
核心思路是对每行的var1和var2排序,基于排序后的组合去重:
import pandas as pd # 构造示例数据 df = pd.DataFrame({ 'var1': ['a', 'b', 'a', 'c', 'b', 'c'], 'var2': ['b', 'a', 'c', 'a', 'c', 'b'], 'value': [0.576, 0.576, 0.987, 0.987, 0.034, 0.034] }) # 对每行的var1、var2排序,生成临时列 df[['sorted1', 'sorted2']] = pd.DataFrame( df[['var1', 'var2']].apply(sorted, axis=1).tolist(), index=df.index ) # 基于排序后的列去重,保留首次出现的行并删除临时列 df_unique = df.drop_duplicates(subset=['sorted1', 'sorted2'], keep='first').drop(columns=['sorted1', 'sorted2']) print(df_unique)
输出结果:
var1 var2 value 0 a b 0.576 2 a c 0.987 4 b c 0.034
方法二:R 语言 dplyr 实现
通过生成排序后的组合标识去重:
library(dplyr) # 构造示例数据 df <- data.frame( var1 = c("a", "b", "a", "c", "b", "c"), var2 = c("b", "a", "c", "a", "c", "b"), value = c(0.576, 0.576, 0.987, 0.987, 0.034, 0.034) ) # 生成排序后的组合标识,去重后删除标识列 df_unique <- df %>% rowwise() %>% mutate(sorted_pair = paste(sort(c(var1, var2)), collapse = "_")) %>% ungroup() %>% distinct(sorted_pair, .keep_all = TRUE) %>% select(-sorted_pair) print(df_unique)
输出结果:
# A tibble: 3 × 3 var1 var2 value <chr> <chr> <dbl> 1 a b 0.576 2 a c 0.987 3 b c 0.034
额外优化:从原始矩阵直接生成无重复长格式
如果还未执行melt,可以直接提取矩阵的上三角(不含对角线)数据,避免后续去重:
Pandas 版本
import pandas as pd import numpy as np # 原始矩阵 mat = pd.DataFrame({ 'a': [0, 0.576, 0.987], 'b': [0.576, 0, 0.034], 'c': [0.987, 0.034, 0] }, index=['a', 'b', 'c']) # 提取上三角数据 df_long = mat.where(np.triu(np.ones(mat.shape), k=1).astype(bool)).stack().reset_index() df_long.columns = ['var1', 'var2', 'value'] print(df_long)
R 版本
library(tidyr) library(dplyr) # 原始矩阵 mat <- matrix(c(0, 0.576, 0.987, 0.576, 0, 0.034, 0.987, 0.034, 0), nrow=3, ncol=3, dimnames=list(c("a","b","c"), c("a","b","c"))) # 提取上三角数据 df_long <- mat %>% as.data.frame() %>% rownames_to_column("var1") %>% pivot_longer(-var1, names_to="var2", values_to="value") %>% filter(upper.tri(mat, diag=FALSE)) print(df_long)
内容的提问来源于stack exchange,提问作者Lucy
相关产品推荐
相关产品推荐

