Python中Scipy分离距离矩阵计算与聚类结果不一致问题排查
预计算距离矩阵后层次聚类结果不一致的解决方法
问题背景
我正在使用Python处理一个二进制DataFrame,其中存储了不同用户在不同时间点的0和1值。原本直接对DataFrame执行层次聚类的代码能得到正确结果:
metodo='average' clusters = linkage(user_df, method=metodo, metric='hamming') # 绘制树状图 plt.figure(figsize=(10, 7)) dendrogram(clusters, labels=user_df.index, leaf_rotation=90) plt.title('Hierarchical Clustering Dendrogram') plt.xlabel('User') plt.ylabel('Distance') plt.savefig(f'dendrogram_{metodo}_entero.png') plt.show()
但尝试将距离矩阵计算与聚类操作分离后,结果和原方法不一致:
dist_matrix = pdist(user_df.values, metric='hamming') # 转换为平方形式并转为DataFrame dist_matrix_square = squareform(dist_matrix) dist_df = pd.DataFrame(dist_matrix_square, index=user_df.index, columns=user_df.index) clusters = linkage(dist_df, method=metodo)
想知道是否可以通过预计算距离矩阵进行聚类,以及正确的实现方式。
原因分析
问题出在linkage函数对输入的要求:当传入预计算的距离矩阵时,必须是pdist返回的压缩一维数组形式,而不是平方形式的方阵(或DataFrame)。
你手动转成方阵后传给linkage,函数会错误地将这个方阵当作样本特征矩阵处理(把每一行视为一个样本的特征向量),这和原方法的逻辑完全不同,因此得到的聚类结果自然不一致。而原方法直接传入DataFrame时,linkage内部会自动调用pdist生成压缩形式的距离矩阵,逻辑正确。
正确实现方式
预计算距离矩阵完全可行,但要直接将pdist返回的压缩数组传给linkage,无需转成方阵或DataFrame:
metodo='average' # 预计算压缩形式的距离矩阵 dist_matrix = pdist(user_df.values, metric='hamming') # 直接传入压缩距离矩阵执行聚类 clusters = linkage(dist_matrix, method=metodo) # 绘制树状图(和原代码一致) plt.figure(figsize=(10, 7)) dendrogram(clusters, labels=user_df.index, leaf_rotation=90) plt.title('Hierarchical Clustering Dendrogram') plt.xlabel('User') plt.ylabel('Distance') plt.savefig(f'dendrogram_{metodo}_entero.png') plt.show()
如果后续需要使用平方形式的距离矩阵做其他分析,依然可以保留dist_df的生成,但聚类操作必须依赖pdist返回的压缩数组。
内容的提问来源于stack exchange,提问作者slow_learner
相关产品推荐
相关产品推荐

