如何基于Diff属性实现相似数据项的聚类分组?
基于相似度对比结果的聚类实现方案
核心思路
你已经有了所有数据项的两两Diff值(Diff越小相似度越高),可以将这些值转换成距离矩阵(Diff值直接作为距离,因为相似度高对应距离小),再用基于距离的聚类算法完成分组。Pandas可用于快速构建距离矩阵,搭配Scikit-learn、SciPy的工具就能实现聚类。
具体步骤
1. 用Pandas构建距离矩阵
首先把对比对集合转换成结构化的DataFrame,再生成对称的距离矩阵:
import pandas as pd import numpy as np # 假设pairs是已有的对比对列表 df_pairs = pd.DataFrame(pairs) # 提取所有数据项的唯一标识(用path代替对象本身,方便后续处理) all_paths = pd.concat([ df_pairs['a'].apply(lambda x: x['path']), df_pairs['b'].apply(lambda x: x['path']) ]).unique() # 初始化距离矩阵,默认填充极大值(表示未计算的配对) distance_matrix = pd.DataFrame( np.inf, index=all_paths, columns=all_paths ) # 对角线元素设为0(自身和自身的距离为0) np.fill_diagonal(distance_matrix.values, 0) # 填充已有的Diff值,保证矩阵对称 for _, row in df_pairs.iterrows(): path_a = row['a']['path'] path_b = row['b']['path'] distance_matrix.loc[path_a, path_b] = row['diff'] distance_matrix.loc[path_b, path_a] = row['diff']
2. 选择合适的聚类算法
层次聚类(适合需要明确分组的场景)
层次聚类可以基于距离矩阵生成树状图,方便你直观判断分组数量:
from scipy.cluster.hierarchy import linkage, dendrogram, fcluster import matplotlib.pyplot as plt # 将距离矩阵转换为SciPy要求的压缩格式 condensed_dist = distance_matrix.values[np.triu_indices_from(distance_matrix, k=1)] # 构建聚类树(ward方法最小化组内方差,也可选用single/complete等) linkage_matrix = linkage(condensed_dist, method='ward') # 绘制树状图,观察分组逻辑 plt.figure(figsize=(10, 6)) dendrogram(linkage_matrix, labels=all_paths) plt.title('聚类树状图') plt.xlabel('数据项路径') plt.ylabel('距离(Diff值)') plt.show() # 根据树状图选择距离阈值,生成聚类结果 cluster_labels = fcluster(linkage_matrix, t=50000, criterion='distance') # t为自定义阈值 # 整理结果 result = pd.DataFrame({'path': all_paths, 'cluster': cluster_labels}) print(result)
DBSCAN(适合自动识别密度聚类)
如果你的数据存在天然的密度聚集结构,DBSCAN可以自动识别核心聚类和噪声点,无需提前指定分组数:
from sklearn.cluster import DBSCAN from sklearn.preprocessing import StandardScaler # 将距离矩阵转为特征矩阵形式 X = distance_matrix.values # 标准化数据(根据Diff值范围可选) X_scaled = StandardScaler().fit_transform(X) # 初始化DBSCAN,使用预计算的距离矩阵 dbscan = DBSCAN(eps=50000, min_samples=2, metric='precomputed') cluster_labels = dbscan.fit_predict(X) # 整理结果 result = pd.DataFrame({'path': all_paths, 'cluster': cluster_labels}) print(result)
3. 关键注意点
- 阈值选择:根据Diff值的实际分布调整,比如看层次聚类树状图的“断层”位置,或通过统计Diff值的分位数确定。
- 数据标识:用
path作为数据项的唯一标识,避免直接操作对象,降低处理复杂度。 - 算法适配:层次聚类适合需要清晰分组边界的场景;DBSCAN更适合存在密度差异的数据集,若Diff值分布均匀,优先选择层次聚类。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

