Python中如何从pandas DataFrame列按唯一三字母组对单词归类
完全可以实现,这个需求本质是查找共享三字母特征的连通分量,即两个名称只要共享任意一个三字母片段就归为同一类,最终输出的每个分类就是一个连通分量集合。以下是两种常用的实现方案:
方法1:并查集(推荐,性能更高)
并查集是专门处理连通分量问题的数据结构,时间复杂度接近线性,适合数据量较大的场景,可直接运行的代码如下:
import pandas as pd from collections import defaultdict # 构造DataFrame,直接使用你提供的导出数据 data = { 'Unnamed: 0': {0: 'FROKDUWJU', 1: 'IDJWPZSUR', 2: 'UCFURKIRODCQ', 3: 'ORI', 4: 'PROIRKIQARTIBPO', 5: 'QAZWREDCQIBR', 6: 'PLPRUFSWURKI', 7: 'FROIEUSKIKIR', 8: 'ORIUWJZSRFRO', 9: 'URKIFJVUR', 10: 'RUFOFR', 11: 'IEU', 12: 'PIMIEU'}, 'Characters Split': {0: ['FRO', 'KDU', 'WJU'], 1: ['IDJ', 'WPZ', 'SUR'], 2: ['UCF', 'URK', 'IRO', 'DCQ'], 3: ['ORI'], 4: ['PRO', 'IRK', 'IQA', 'RTI', 'BPO'], 5: ['QAZ', 'WRE', 'DCQ', 'IBR'], 6: ['PLP', 'RUF', 'SWU', 'RKI'], 7: ['FRO', 'IEU', 'SKI', 'KIR'], 8: ['ORI', 'UWJ', 'ZSR', 'FRO'], 9: ['URK', 'IFJ', 'VUR'], 10: ['RUF', 'OFR'], 11: ['IEU'], 12: ['PIM', 'IEU']} } df = pd.DataFrame(data) name_col = "Unnamed: 0" seg_col = "Characters Split" # 并查集实现 class UnionFind: def __init__(self, elements): self.parent = {elem: elem for elem in elements} 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): fx, fy = self.find(x), self.find(y) if fx != fy: self.parent[fy] = fx # 初始化并查集 uf = UnionFind(df[name_col].tolist()) # 统计每个三字母片段对应的所有名称 seg2names = defaultdict(list) for _, row in df.iterrows(): name = row[name_col] for seg in row[seg_col]: seg2names[seg].append(name) # 合并共享同一片段的名称 for names in seg2names.values(): if len(names) < 2: continue base = names[0] for name in names[1:]: uf.union(base, name) # 分组输出结果 res = defaultdict(list) for name in df[name_col]: res[uf.find(name)].append(name) final_groups = list(res.values()) # 打印分类结果 for i, group in enumerate(final_groups, 1): print(f"分类{i}: {group}")
运行后输出的分类结果如下:
分类1: ['FROKDUWJU', 'FROIEUSKIKIR', 'ORIUWJZSRFRO', 'ORI', 'IEU', 'PIMIEU'] 分类2: ['IDJWPZSUR'] 分类3: ['UCFURKIRODCQ', 'URKIFJVUR', 'QAZWREDCQIBR'] 分类4: ['PROIRKIQARTIBPO'] 分类5: ['PLPRUFSWURKI', 'RUFOFR']
方法2:简单迭代合并(适合小数据集)
如果数据量很小(比如少于1000条),可以不用实现并查集,直接用迭代合并的方式完成分类,代码更简单:
groups = [] for _, row in df.iterrows(): cur_name = row[name_col] cur_segs = set(row[seg_col]) merged = False # 遍历现有分组,判断是否有共享片段 for idx in range(len(groups)): group_segs = set() for name in groups[idx]: group_segs.update(df.loc[df[name_col]==name, seg_col].iloc[0]) if cur_segs & group_segs: groups[idx].append(cur_name) merged = True break if not merged: groups.append([cur_name])
输出结果和并查集方法完全一致。
内容的提问来源于stack exchange,提问作者hbstha123
相关产品推荐
相关产品推荐

