Gridspec子图标签位置不一致:如何统一标签绝对偏移距离?
问题:Gridspec创建的不同尺寸子图标签偏移不一致
我用Gridspec创建了不同尺寸的子图,想在每个子图左上角外部添加标签,但结果各标签的偏移距离不一样。推测是因为x、y偏移量是坐标轴尺寸的函数,请问最优雅的方法能让所有标签到对应子图的绝对水平和垂直距离一致?
我的代码如下:
import numpy as np from matplotlib import pyplot as plt from matplotlib.gridspec import GridSpec def label_panels(fig, panels, xloc = -0.1, yloc = 1.2, size = 20): for n, ax in enumerate(fig.axes): if n < len(panels): ax.text(xloc, yloc, panels[n], size=size, weight='bold') fig_7 = plt.figure(constrained_layout=True, figsize = (4,5)) fig7_gs = GridSpec(5, 4, figure=fig_7) exemplars_subplots = np.array([[fig_7.add_subplot(fig7_gs[i:i+1, j]) for i in range(2)] for j in range(4)]) STDP_subplots = [fig_7.add_subplot(fig7_gs[2+i:3+i,0:2]) for i in range(3)] ax_imshow = fig_7.add_subplot(fig7_gs[2:5, 2:4]) label_panels(fig_7, range(len(fig_7.axes)), xloc = -0.25, yloc = 1.2) plt.show()
效果:子图0-7、8-10和11的标签偏移距离明显不一致。
解决办法:用图形坐标系定位标签
核心办法就是别用子图自己的坐标轴坐标系,改用整个图形的绝对坐标系来放标签,这样不管子图尺寸多大,标签到子图的绝对距离都能保持一致。具体操作:
- 先拿到每个子图在整个图形里的位置(左下角和右上角的坐标)
- 给标签设置固定的像素偏移量(比如往左挪10像素,往上挪5像素,数值可以自己调)
- 把偏移后的像素位置转换成图形坐标系的数值,再把标签放上去
修改后的代码:
import numpy as np from matplotlib import pyplot as plt from matplotlib.gridspec import GridSpec def label_panels(fig, panels, x_offset=-10, y_offset=5, size=20): dpi = fig.dpi for n, ax in enumerate(fig.axes): if n >= len(panels): continue # 获取子图在图形中的相对位置([左, 底, 宽, 高],范围0-1) pos = ax.get_position() # 计算标签的像素位置:子图左上角向左/向上偏移指定像素 fig_w_pix = fig.get_figwidth() * dpi fig_h_pix = fig.get_figheight() * dpi label_x_pix = pos.x0 * fig_w_pix + x_offset label_y_pix = (pos.y0 + pos.height) * fig_h_pix + y_offset # 转成图形坐标系的0-1范围数值 label_x = label_x_pix / fig_w_pix label_y = label_y_pix / fig_h_pix # 在图形坐标系下添加标签 fig.text(label_x, label_y, str(panels[n]), size=size, weight='bold', ha='right', va='bottom') fig_7 = plt.figure(constrained_layout=True, figsize=(4,5)) fig7_gs = GridSpec(5, 4, figure=fig_7) exemplars_subplots = np.array([[fig_7.add_subplot(fig7_gs[i:i+1, j]) for i in range(2)] for j in range(4)]) STDP_subplots = [fig_7.add_subplot(fig7_gs[2+i:3+i,0:2]) for i in range(3)] ax_imshow = fig_7.add_subplot(fig7_gs[2:5, 2:4]) # 这里的x_offset和y_offset是像素值,按需调整 label_panels(fig_7, range(len(fig_7.axes)), x_offset=-10, y_offset=5) plt.show()
关键说明
ax.get_position():获取子图在整个画布上的相对位置(范围0到1),不受子图自身尺寸影响- 通过DPI将像素偏移转换为图形坐标系的数值,确保在不同尺寸的画布上偏移量都一致
- 使用
fig.text()而不是ax.text(),直接在图形坐标系下绘制文本,避免子图坐标系的缩放影响
内容的提问来源于stack exchange,提问作者tmldwn
相关产品推荐
相关产品推荐

