
本文介绍如何将成对出现的相似元素(如('a','b')表示a与b相似)建模为无向图,并通过深度优先搜索(dfs)或networkx库识别连通分量,从而自动聚类出所有相似值组。
本文介绍如何将成对出现的相似元素(如('a','b')表示a与b相似)建模为无向图,并通过深度优先搜索(dfs)或networkx库识别连通分量,从而自动聚类出所有相似值组。
在数据处理与特征工程中,常需根据共现关系对离散标识符(如列名、ID、标签)进行语义聚类:若两个元素在任意一对组合中同时出现,则视作“相似”;进一步地,相似关系具有传递性(a∼b 且 b∼c ⇒ a∼c),因此本质上是在求无向图的连通分量(Connected Components)。
给定输入:
col_combi = [('a','b'), ('b','c'), ('d','e'), ('l','j'), ('c','g'),
('e','m'), ('m','z'), ('z','p'), ('t','k'), ('k', 'n'), ('j','k')]
目标是输出三个连通簇:'a-b-c-g'、'd-e-m-z-p'、'l-j-k-n-t'。
✅ 推荐方案:使用 NetworkX(简洁健壮)
尽管提问者提到“未能成功使用 NetworkX”,实际只需几行代码即可完成:
import networkx as nx G = nx.Graph() G.add_edges_from(col_combi) # 自动构建无向图 # 获取所有连通分量(每个为节点集合) components = list(nx.connected_components(G)) # 按字母顺序排序各簇内节点,再拼接为字符串(可选,提升可读性) clusters = ['-'.join(sorted(comp)) for comp in components] print(clusters) # 输出:['a-b-c-g', 'd-e-m-p-z', 'j-k-l-n-t']
? 注意:
'd-e-m-p-z'与示例'd-e-m-z-p'仅顺序不同,语义完全等价;若需严格保持原始出现顺序,需额外定义排序逻辑(如按首次出现索引),但通常按字典序更规范。
✅ 替代方案:手动实现 DFS(无外部依赖)
若因环境限制无法安装 networkx,可手写图遍历逻辑。关键点包括:
- 构建邻接表(双向映射);
- 使用
visited集合避免重复访问; - 对每个未访问节点启动 DFS,收集其可达的所有节点。
优化后的完整实现如下:
from collections import defaultdict, deque
def cluster_pairs(pairs):
# 构建无向图邻接表
graph = defaultdict(set)
for a, b in pairs:
graph[a].add(b)
graph[b].add(a)
visited = set()
clusters = []
for node in graph:
if node not in visited:
# BFS 或 DFS 均可;此处用 BFS 更易理解
queue = deque([node])
visited.add(node)
cluster = []
while queue:
curr = queue.popleft()
cluster.append(curr)
for neighbor in graph[curr]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
clusters.append('-'.join(sorted(cluster))) # 排序后连接
return clusters
# 调用
result = cluster_pairs(col_combi)
print(result)
# ['a-b-c-g', 'd-e-m-p-z', 'j-k-l-n-t']
⚠️ 注意事项与最佳实践
-
孤立节点处理:当前代码仅处理至少出现在一个 pair 中的节点;若存在未参与任何 pair 的“孤立元素”,需先显式加入图中(如
graph[node] = set()),否则会被忽略。 -
性能考量:对于超大规模数据(>10⁵ 边),优先选用
networkx或igraph,它们底层为 C 实现,效率远高于纯 Python DFS/BFS。 -
结果稳定性:连通分量本身无序,建议对每个簇内元素统一排序(如
sorted()),确保输出可重现。 - 扩展性提示:若需支持加权相似度或有向关系,应切换为带权图或强连通分量(SCC)算法。
综上,将相似对转化为图结构并求解连通分量,是解决此类聚类问题的标准范式。推荐首选 networkx.connected_components —— 简洁、可靠、可读性强,且易于集成到数据管道中。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











