如何将Matplotlib柱状图与Seaborn聚类图子图对齐?
解决Clustermap上方添加列均值柱状图的问题
为啥会报错?
sns.clustermap 是个自带完整布局的高阶工具——它会自动生成聚类图、树状图、颜色条这套完整结构,内部已经创建了颜色条的轴(cbar_ax)。你像用heatmap那样手动传这个参数,就等于重复赋值,直接触发TypeError,这和heatmap那种在你指定的子图上绘图的逻辑完全不同。
可行的实现方法
按以下步骤来,能完美对齐还不报错:
- 先画聚类图,拿好布局信息:先运行
clustermap得到返回的ClusterGrid对象,它里面存了聚类后的列顺序、各个轴的位置,这是对齐的关键。 - 算出聚类后的列均值:根据
ClusterGrid里的col_order,把原始数据按聚类后的列顺序重新排,再算每列的均值。 - 在聚类图上方插子图:从
ClusterGrid里拿到主热图的位置,用这个位置坐标在上方新建一个子图,保证宽度和主热图完全对齐。 - 画柱状图并调样式:在新子图上画列均值的柱状图,调整标签、间距,别和下面的聚类图重叠。
示例代码
import seaborn as sns import matplotlib.pyplot as plt import numpy as np # 生成测试数据 np.random.seed(42) data = np.random.rand(10, 8) # 1. 先画聚类图,获取ClusterGrid对象 cg = sns.clustermap(data, cmap="viridis", figsize=(8, 6)) # 2. 按聚类后的列顺序,计算每列的均值 col_order = cg.dendrogram_col.reordered_ind mean_vals = data[:, col_order].mean(axis=0) # 3. 在聚类图上方创建对齐的子图 # 先拿到主热图的位置坐标 ax_heatmap = cg.ax_heatmap pos = ax_heatmap.get_position() # 新建子图:x、y坐标,宽度和主热图一致,高度设为主热图的1/5 ax_bar = plt.axes([pos.x0, pos.y1 + 0.02, pos.width, pos.height/5]) # 4. 绘制列均值柱状图 ax_bar.bar(range(len(mean_vals)), mean_vals, color="#1f77b4") # 调整样式,避免重叠 ax_bar.set_xticks([]) # 去掉x轴刻度,和下方聚类图的列标签不重复 ax_bar.set_ylabel("列均值") plt.title("聚类图 + 列均值柱状图", y=1.2) # 整体调整布局,防止标题和子图挤在一起 plt.tight_layout() plt.show()
重点提醒
- 不用手动处理
cbar_ax,clustermap自己会搞定颜色条的位置 - 必须用
col_order来对齐列顺序,不然柱状图和聚类图的列对应不上 - 通过主热图的位置坐标创建子图,能保证两者宽度完全对齐
内容的提问来源于stack exchange,提问作者Johnny Tam
相关产品推荐
相关产品推荐

