You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让热力图次坐标轴Y轴刻度居中并显示边缘边框

问题描述

我有如下数据框:

l1 = ['A','A','A','A','A','A','A','A','A','A','B','B','B','B','B','B','B','B','B','B']
l2 = ['Name-1','Name-2','Name-3','Name-4','Name-5','Name-6','Name-7','Name-8','Name-9','Name-10','Name-11','Name-12','Name-13','Name-14','Name-15','Name-16','Name-17','Name-18','Name-19','Name-20']
v1 = [1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1]
v2 = [0,0,0,1,1,1,0,0,1,1,0,0,0,1,1,1,0,0,1,1]
v3 = [1,0,1,1,1,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0]
v4 = [0,0,0,0,1,1,1,0,0,1,0,0,0,0,1,1,1,0,0,1]
v5 = [1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,1]
v6 = [1,1,0,0,1,1,0,1,0,1,1,1,0,0,1,1,0,1,0,1]
v7 = [0,0,1,1,0,0,1,1,0,1,0,0,1,1,0,0,1,1,0,1]
v8 = [0,1,0,1,1,1,1,0,1,1,0,1,0,1,1,1,1,0,1,1]
v9 = [1,1,0,1,1,1,0,0,0,1,1,1,0,1,1,1,0,0,0,1]
v10 =[1,1,1,0,0,0,1,1,0,1,1,1,1,0,0,0,1,1,0,1]
d = {'variable': l1, 'value': l2,'ID1': v1,'ID2': v2,'ID3': v3,'ID4': v4,'ID5': v5,'ID6': v6,'ID7': v7,'ID8': v8,'ID9': v9,'ID10': v10} 
df = pd.DataFrame(d)
df = df.set_index(['variable','value'])

sum_list = df.sum(axis=0)

我绘制了左右两侧带Y轴刻度的热力图,代码如下:

sns.set(rc={'figure.figsize': (10,10),'xtick.labelsize': 12,'ytick.labelsize': 12, 'axes.labelcolor': 'black',
           'ytick.left': True, 'ytick.right': True,'axes.grid': False,})
heat_map = sns.heatmap(df.reset_index(level='variable', col_level=0,drop=True),square=False,yticklabels=True,xticklabels=False,cmap=['#FFFFFF','#ff0303'],vmin=0,vmax=1,cbar=False,linewidths=1,linecolor='black', annot_kws={"fontsize":3})
heat_map.set_yticklabels(labels=heat_map.get_yticklabels(),weight='bold',color='black')
heat_map.set(xlabel=None,ylabel=None)
sec_axis=heat_map.twinx()
sec_axis.set_yticks(heat_map.get_yticks())
sec_axis.set_yticklabels(df.sum(axis=1).values[::-1], weight='bold', color='black', fontsize=12) ## Add tick labels which will be the sum
sec_axis.grid(False)

现在遇到两个问题:

  • 添加右侧次坐标轴后,热力图四边边缘消失
  • 右侧Y轴刻度未居中对齐

需要实现两个需求:

  1. 显示热力图并保留四边边缘
  2. 将次坐标轴Y轴刻度居中对齐

解决方案

1. 恢复热力图四边边缘

twinx()会默认隐藏原轴的右侧边框,同时可能导致整体边框被遮挡。只需手动开启原轴的四边边框,并调整次轴的边框显示逻辑,再优化布局避免裁剪:

在创建次坐标轴后添加以下代码:

# 恢复原热力图轴的四边边框
heat_map.spines[['top', 'bottom', 'left', 'right']].set_visible(True)
# 隐藏次轴的左、上、下边框,仅保留右侧边框
sec_axis.spines[['top', 'bottom', 'left']].set_visible(False)
sec_axis.spines['right'].set_visible(True)
# 调整布局,确保边框不被画布裁剪
plt.tight_layout()

2. 让右侧Y轴刻度居中对齐

原代码直接复用原轴的刻度位置,而热力图的行中心和刻度位置不匹配。需要计算每行的中心坐标来设置次轴刻度:

替换原有的sec_axis.set_yticks(...)和sec_axis.set_yticklabels(...)代码,改为:

# 获取热力图的Y轴范围
y_min, y_max = heat_map.get_ylim()
# 计算每行的中心位置:总共有len(df)行,每行高度为(y_max - y_min)/len(df)
yticks = [y_min + (i + 0.5)*(y_max - y_min)/len(df) for i in range(len(df))]
# 设置次轴刻度为行中心位置
sec_axis.set_yticks(yticks)
# 设置刻度标签,无需反转顺序
sec_axis.set_yticklabels(df.sum(axis=1).values, weight='bold', color='black', fontsize=12)

完整代码
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt

# 构造数据框
l1 = ['A','A','A','A','A','A','A','A','A','A','B','B','B','B','B','B','B','B','B','B']
l2 = ['Name-1','Name-2','Name-3','Name-4','Name-5','Name-6','Name-7','Name-8','Name-9','Name-10','Name-11','Name-12','Name-13','Name-14','Name-15','Name-16','Name-17','Name-18','Name-19','Name-20']
v1 = [1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1]
v2 = [0,0,0,1,1,1,0,0,1,1,0,0,0,1,1,1,0,0,1,1]
v3 = [1,0,1,1,1,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0]
v4 = [0,0,0,0,1,1,1,0,0,1,0,0,0,0,1,1,1,0,0,1]
v5 = [1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,1]
v6 = [1,1,0,0,1,1,0,1,0,1,1,1,0,0,1,1,0,1,0,1]
v7 = [0,0,1,1,0,0,1,1,0,1,0,0,1,1,0,0,1,1,0,1]
v8 = [0,1,0,1,1,1,1,0,1,1,0,1,0,1,1,1,1,0,1,1]
v9 = [1,1,0,1,1,1,0,0,0,1,1,1,0,1,1,1,0,0,0,1]
v10 =[1,1,1,0,0,0,1,1,0,1,1,1,1,0,0,0,1,1,0,1]
d = {'variable': l1, 'value': l2,'ID1': v1,'ID2': v2,'ID3': v3,'ID4': v4,'ID5': v5,'ID6': v6,'ID7': v7,'ID8': v8,'ID9': v9,'ID10': v10} 
df = pd.DataFrame(d)
df = df.set_index(['variable','value'])

sum_list = df.sum(axis=0)

# 绘制热力图
sns.set(rc={'figure.figsize': (10,10),'xtick.labelsize': 12,'ytick.labelsize': 12, 'axes.labelcolor': 'black',
           'ytick.left': True, 'ytick.right': True,'axes.grid': False,})
heat_map = sns.heatmap(df.reset_index(level='variable', col_level=0,drop=True),square=False,yticklabels=True,xticklabels=False,cmap=['#FFFFFF','#ff0303'],vmin=0,vmax=1,cbar=False,linewidths=1,linecolor='black', annot_kws={"fontsize":3})
heat_map.set_yticklabels(labels=heat_map.get_yticklabels(),weight='bold',color='black')
heat_map.set(xlabel=None,ylabel=None)

# 创建次坐标轴
sec_axis=heat_map.twinx()

# 处理右侧刻度居中问题
y_min, y_max = heat_map.get_ylim()
yticks = [y_min + (i + 0.5)*(y_max - y_min)/len(df) for i in range(len(df))]
sec_axis.set_yticks(yticks)
sec_axis.set_yticklabels(df.sum(axis=1).values, weight='bold', color='black', fontsize=12)

# 恢复热力图四边边缘
heat_map.spines[['top', 'bottom', 'left', 'right']].set_visible(True)
sec_axis.spines[['top', 'bottom', 'left']].set_visible(False)
sec_axis.spines['right'].set_visible(True)

sec_axis.grid(False)
plt.tight_layout()
plt.show()

内容的提问来源于stack exchange,提问作者Yash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 06:16:20