如何基于含重复配对的比较列表替换DataFrame中相同观测的ID
解决方案
你的需求本质是识别两两等价ID构成的连通集合,为每个集合分配统一ID,用并查集(Union-Find) 数据结构可以完美解决重复配对、顺序颠倒的问题,实现步骤如下:
步骤1:实现并查集工具
class UnionFind: def __init__(self): self.parent = {} def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) # 路径压缩提升查询效率 return self.parent[x] def union(self, x, y): # 不存在的ID先加入集合 if x not in self.parent: self.parent[x] = x if y not in self.parent: self.parent[y] = y # 合并两个集合,默认选数值更小的ID作为集合统一标识,可自定义规则 root_x = self.find(x) root_y = self.find(y) if root_x != root_y: if root_x < root_y: self.parent[root_y] = root_x else: self.parent[root_x] = root_y
步骤2:处理配对数据生成映射字典
首先筛选Value=0的等价ID对,全部送入并查集完成合并:
import pandas as pd # 替换为你的比较结果DataFrame变量名 cmp_df = pd.read_csv("你的比较数据文件路径.csv") equal_pairs = cmp_df[cmp_df['Value'] == 0][['idA', 'idB']].values.tolist() uf = UnionFind() for a, b in equal_pairs: uf.union(a, b) # 生成【子ID -> 统一ID】的映射表,用于替换原始数据ID id_map = {} # 生成你需要的【统一ID -> 同组子ID列表】格式 group_map = {} for id_val in uf.parent: root = uf.find(id_val) id_map[id_val] = root if root not in group_map: group_map[root] = [] if id_val != root: group_map[root].append(id_val)
示例数据运行后输出的group_map结果如下,你举例中遗漏的等价ID28527会被自动归到对应集合中:
{49923: [19848, 14780, 13689, 22162], 23549: [47291, 28527, 2576]}
步骤3:处理原始特征DataFrame
# 替换为你的原始特征DataFrame变量名 feat_df = pd.read_csv("你的原始特征数据路径.csv") # 替换ID,没有等价配对的ID保持原值不变 feat_df['id'] = feat_df['id'].map(id_map).fillna(feat_df['id']) # 按ID去重,保留第一个出现的特征行即可 final_df = feat_df.drop_duplicates(subset='id', keep='first').reset_index(drop=True)
输出的final_df就是你需要的、每个特征组仅保留一个统一ID的结果。
内容的提问来源于stack exchange,提问作者ianux22
相关产品推荐
相关产品推荐

