Matplotlib中如何让二级标签位于一级标签下方并调整标记
解决Matplotlib/Seaborn热图的轴标记与标签层级问题
我来帮你搞定这个热图的标记和标签问题,咱们先理清核心需求,再一步步调整代码:
- 在X、Y轴对应数值125、128、130、133、138、142、143的位置,添加大小为16的
*标记 - 让这些
*二级标签位于一级数值标签的下方 - 修复网格偏移的问题
原代码的问题主要是:标记位置未对应实际数值、标记大小未设置、双轴标签位置错误,以及网格和热图单元格未对齐。下面是修改后的完整代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import unicode_literals import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt import matplotlib.ticker as tkr import matplotlib.patches as patches # 读取数据 with open("1.txt") as f: lstx = [int(x) for x in f.read().split()] with open("2.txt") as f: lsty = [int(x) for x in f.read().split()] with open("3.txt") as f: lstz = [float(x) for x in f.read().split()] # 轴标签格式化函数:把0-based刻度转为120+的数值 def numfmt(x, pos): return f'{int(x + 120)}' # 转换为数组并构建DataFrame x = np.array(lstx) y = np.array(lsty) z = np.array(lstz) df = pd.DataFrame(np.array([y, x, z]).T, columns=['X_value','Y_value','Z_value']) df['Z_value'] = pd.to_numeric(df['Z_value']) # 创建热图 fig, ax = plt.subplots(figsize=(11,9)) pivotted = df.pivot('X_value','Y_value','Z_value') ax = sns.heatmap(pivotted, cmap='plasma_r', vmin=0.0, vmax=234.525, cbar=True) # 调整颜色条刻度大小 cbar = ax.collections[0].colorbar cbar.ax.tick_params(labelsize=20) # 反转Y轴(符合热图常见展示逻辑) ax.invert_yaxis() # 设置X/Y轴主刻度格式和大小 xfmt = tkr.FuncFormatter(numfmt) ax.xaxis.set_major_formatter(xfmt) ax.yaxis.set_major_formatter(xfmt) # Y轴格式和X轴一致,直接复用函数 ax.set_xlabel('\nNumber', fontsize=24) ax.set_ylabel('Number\n', fontsize=24) ax.tick_params(axis='both', labelsize=16, pad=15) # 给主标签留空间放二级标记 # ---------------------- 核心修改:添加二级*标记 ---------------------- # 需要标记的目标数值 target_values = [125, 128, 130, 133, 138, 142, 143] # 转换为0-based的轴位置(主刻度0对应120,所以数值减120就是位置) target_positions = [val - 120 for val in target_values] # 在X轴添加*标记(位于主标签下方) for pos in target_positions: ax.annotate('*', xy=(pos, 0), xycoords='data', xytext=(0, -18), textcoords='offset points', fontsize=16, ha='center', va='top') # 在Y轴添加*标记(位于主标签左侧) for pos in target_positions: ax.annotate('*', xy=(0, pos), xycoords='data', xytext=(-18, 0), textcoords='offset points', fontsize=16, ha='right', va='center') # ---------------------- 修复网格偏移问题 ---------------------- # 让网格与热图单元格边界对齐 ax.set_xticks(np.arange(pivotted.shape[1]+1) - 0.5, minor=True) ax.set_yticks(np.arange(pivotted.shape[0]+1) - 0.5, minor=True) ax.grid(which='minor', color='gray', linestyle='-', linewidth=0.5, alpha=0.5) ax.grid(which='major', visible=False) # 关闭主网格,避免和次要网格冲突 # 添加矩形框(保留原需求) rect3 = patches.Rectangle((5-0.5,5-0.5),13,13, linewidth=1.7, linestyle='--', edgecolor='black', facecolor='none') ax.add_patch(rect3) plt.tight_layout() plt.show()
关键修改点说明:
精准定位标记:
- 把目标数值转换成热图的0-based轴位置(
val - 120),确保标记对应正确的单元格 - 用
ax.annotate()代替双轴方案,避免刻度冲突,更灵活控制标记位置
- 把目标数值转换成热图的0-based轴位置(
调整标记样式与位置:
- 通过
xytext设置偏移量,让*刚好落在主标签下方(X轴)或左侧(Y轴) - 直接设置
fontsize=16,确保标记大小符合要求
- 通过
修复网格对齐:
- 把次要刻度设置为热图单元格的边界(
np.arange(shape+1)-0.5),让网格完美贴合单元格 - 关闭主网格,避免和次要网格重叠冲突
- 把次要刻度设置为热图单元格的边界(
优化标签间距:
- 主刻度设置
pad=15,给二级标记留出足够显示空间,避免标签重叠
- 主刻度设置
这样调整后,你的热图就能完全满足所有需求:标记位置准确、大小合适,二级标签在主标签下方,网格也能完美对齐热图单元格。
内容的提问来源于stack exchange,提问作者Hdez
相关产品推荐
相关产品推荐

