如何绘制带分类色条的系统树图,复刻seaborn.clustermap树图效果且不含热图
完整实现代码
import seaborn as sns import matplotlib.pyplot as plt from scipy.cluster.hierarchy import linkage, dendrogram from mpl_toolkits.axes_grid1 import make_axes_locatable import matplotlib.patches as mpatches # 准备数据 sns.set_theme(color_codes=True) iris = sns.load_dataset("iris") species = iris.pop("species") lut = dict(zip(species.unique(), ["r", "b", "g"])) row_colors = species.map(lut).tolist() # 聚类计算 Z = linkage(iris, method='average', metric='euclidean') # 绘图 with plt.rc_context({'lines.linewidth': 0.5}): fig, ax = plt.subplots(figsize=(3, 6)) ax.axis('off') # 绘制树状图,获取聚类后叶节点的排序 dd = dendrogram(Z, ax=ax, truncate_mode=None, leaf_rotation=0, color_threshold=0, above_threshold_color='black', no_labels=True, orientation='left') # 按照聚类后的顺序重排分类颜色 sorted_row_colors = [row_colors[i] for i in dd['leaves']] sample_count = len(sorted_row_colors) # 创建右侧分类色条的轴 divider = make_axes_locatable(ax) color_ax = divider.append_axes('right', size='5%', pad=0.05) color_ax.axis('off') # 逐个绘制分类色块,和树的叶节点一一对应 for idx, color in enumerate(sorted_row_colors): color_ax.add_patch(mpatches.Rectangle((0, idx), 1, 1, color=color)) # 调整色条轴范围刚好容纳所有色块 color_ax.set_xlim(0, 1) color_ax.set_ylim(0, sample_count) # 生成分类图例 legend_items = [mpatches.Patch(color=color, label=label) for label, color in lut.items()] ax.legend(handles=legend_items, bbox_to_anchor=(1.5, 1), loc='upper left', frameon=False) plt.show()
问题解决说明
- 分类色条映射问题:你之前调用
colorbar的方案不适用,colorbar是为连续数值色阶设计的,无法匹配离散分类场景。我们通过dendrogram返回的leaves字段拿到聚类后的样本排序,将分类颜色按该顺序重排后手动绘制对应色块,即可保证色条和树图的位置完全对应,和seaborn.clustermap的row_colors效果一致。 - 分类图例生成问题:用
matplotlib.patches.Patch为每个分类创建带对应颜色的图例块,绑定分类标签后传入legend方法即可生成自定义分类图例,调整bbox_to_anchor参数可控制图例位置避免遮挡。
内容的提问来源于stack exchange,提问作者skurp
相关产品推荐
相关产品推荐

