如何在Matplotlib中正确连接两个层次聚类树状图?
解决Matplotlib层次聚类树状图标签连线错位问题
问题说明
使用Matplotlib绘制两个数据集(X1、X2)的层次聚类树状图并并排展示时,无法正确连接两个树状图的对应标签,连线出现错位或缺失。
错误原因
原代码中匹配右侧标签时,使用names.index(left_name)获取的是原始数据索引,而非该标签在右侧树状图叶子中的实际位置。右侧树状图的叶子顺序由dn2['leaves']决定,必须通过原始索引找到其在该列表中的位置,才能得到正确的y坐标。
修正后的代码
import matplotlib.pyplot as plt import scipy.cluster.hierarchy as hierarchy import numpy as np # 样本数据 np.random.seed(20240406) X1 = np.random.rand(10, 12) X2 = np.random.rand(10, 12) names = ['Jack', 'Oxana', 'John', 'Chelsea', 'Mark', 'Alice', 'Charlie', 'Rob', 'Lisa', 'Lily'] # 创建画布和子图,sharey=True确保y轴对齐 fig, axes = plt.subplots(1, 3, figsize=(12, 6), sharey=True) # 绘制左侧树状图(X1) Z1 = hierarchy.linkage(X1, method='complete') dn1 = hierarchy.dendrogram(Z1, ax=axes[0], orientation='left', labels=names) axes[0].set_title('Left Dendrogram for X1') axes[0].set_xlabel('Distance') # 绘制右侧树状图(X2) Z2 = hierarchy.linkage(X2, method='complete') dn2 = hierarchy.dendrogram(Z2, ax=axes[2], orientation='right', labels=names) axes[2].set_title('Right Dendrogram for X2') axes[2].set_xlabel('Distance') # 获取左右树状图的叶子顺序(原始数据索引) leaves_left = dn1['leaves'] leaves_right = dn2['leaves'] # 构建正确的连接关系:左侧叶子位置 ↔ 右侧叶子位置 connections = [] for left_pos, original_idx in enumerate(leaves_left): try: # 找到原始索引在右侧叶子中的位置 right_pos = leaves_right.index(original_idx) connections.append((left_pos, right_pos)) except ValueError: continue # 标签不存在则跳过 # 绘制跨轴连接线 for left_y, right_y in connections: # 转换左右子图坐标到中间子图坐标系 left_point = axes[0].transAxes.transform((1, left_y)) right_point = axes[2].transAxes.transform((0, right_y)) left_in_middle = axes[1].transData.inverted().transform(left_point) right_in_middle = axes[1].transData.inverted().transform(right_point) axes[1].plot([left_in_middle[0], right_in_middle[0]], [left_in_middle[1], right_in_middle[1]], 'k-', alpha=0.5) # 配置中间子图 axes[1].set_title('Connections') axes[1].axis('off') plt.tight_layout() plt.show()
关键修正点
sharey=True:创建子图时启用该参数,确保三个子图的y轴范围、刻度完全对齐,从根源避免轴范围不一致导致的错位。- 精准匹配叶子位置:通过
leaves_right.index(original_idx)获取标签在右侧树状图中的实际y坐标,而非使用原始数据索引。 - 跨轴坐标转换:利用Matplotlib的坐标转换工具,将左右子图的坐标映射到中间子图坐标系,保证跨轴连线的精准对齐。
内容的提问来源于stack exchange,提问作者Umar
相关产品推荐
相关产品推荐

