Matplotlib左下角子图无法呈正方形及标题位置异常问题咨询
问题:Matplotlib子图布局异常(左下角子图非正方形、标题位置过高)
尝试构建2×2子图布局,要求左下角子图为完美正方形,编写了如下代码:
import matplotlib.pyplot as plt import numpy as np fig=plt.figure() ax=np.empty((2,2,),dtype=object) ax[1][0]=fig.add_subplot(2,2,3) ax[0][0]=fig.add_subplot(2,2,1,sharex=ax[1][0]) ax[1][1]=fig.add_subplot(2,2,4,sharey=ax[1][0]) ax[0][1]=fig.add_subplot(2,2,2,sharex=ax[1][1],sharey=ax[0][0]) plt.subplots_adjust(hspace=0,wspace=0) old_position,old_position2,old_position3,old_position4=list(ax[0][0].get_position().bounds),list(ax[1][1].get_position().bounds),list(ax[1][0].get_position().bounds),list(ax[0][1].get_position().bounds) old_position[-1]=old_position[-1]/2 old_position2[-2]=old_position2[-2]/2 old_position3[-1]=old_position3[-2] old_position4[-1]=old_position4[-1]/2 old_position4[-2]=old_position4[-2]/2 ax[0][0].set_position(old_position) ax[1][1].set_position(old_position2) ax[1][0].set_position(old_position3) ax[0][1].set_position(old_position4) ax[0][0].xaxis.set_visible(False) ax[0][1].xaxis.set_visible(False) ax[1][1].yaxis.set_visible(False) ax[0][1].yaxis.set_visible(False) #plot stuff onto axes objects plt.suptitle('Test') plt.show()
代码中设置左下角子图的位置参数old_position3为[0.125, 0.10999999999999999, 0.38749999999999996, 0.38749999999999996],宽高维度均为0.3874,理论上应呈现正方形,但实际显示时宽高比约为3/5,并非正方形;同时图的suptitle位置过高,仍沿用旧布局的位置。
异常原因
- 归一化坐标与画布比例不匹配:
get_position().bounds返回的是基于整个画布的归一化坐标(范围0-1),如果画布本身不是正方形,归一化的宽高数值相等时,对应的实际像素宽高并不相等。比如画布是宽屏比例,相同归一化数值的宽度对应的像素数会远大于高度,视觉上就不是正方形。 - 标题位置未随布局更新:
suptitle默认基于初始子图布局计算位置,手动调整子图位置后,标题不会自动重新适配,所以会停留在原布局的顶部区域。
解决办法
1. 让左下角子图呈现视觉正方形
方法一:使用正方形画布
创建画布时指定宽高相等的尺寸,这样归一化坐标的宽高相等就对应视觉上的正方形:
fig = plt.figure(figsize=(8, 8)) # 宽高均为8英寸的正方形画布
方法二:强制子图坐标轴比例为1
给左下角子图设置aspect='equal',强制坐标轴的宽高比为1,不管画布比例如何,子图都会呈现正方形:
ax[1][0].set_aspect('equal', adjustable='box')
方法三:基于画布尺寸计算对应高度
如果需要保留非正方形画布,可通过画布实际尺寸计算子图的归一化高度,确保实际像素宽高相等:
fig = plt.figure(figsize=(10, 6)) fig_width, fig_height = fig.get_size_inches() subplot_width = old_position3[2] # 计算对应归一化高度,保证实际像素宽高一致 subplot_height = subplot_width * fig_width / fig_height old_position3[3] = subplot_height ax[1][0].set_position(old_position3)
2. 调整suptitle位置
方法一:手动设置标题垂直位置
通过y参数调整标题的垂直位置,值越小越靠下:
plt.suptitle('Test', y=0.95) # 根据实际布局调整y值
方法二:用tight_layout自动适配
调用tight_layout并通过rect参数预留标题空间,让标题自动适配新布局:
plt.tight_layout(rect=[0, 0, 1, 0.95]) # rect=[左, 下, 右, 上],预留顶部空间给标题 plt.suptitle('Test')
优化后的完整代码示例
import matplotlib.pyplot as plt import numpy as np # 使用正方形画布 fig = plt.figure(figsize=(8, 8)) ax = np.empty((2,2), dtype=object) ax[1][0] = fig.add_subplot(2,2,3) ax[0][0] = fig.add_subplot(2,2,1, sharex=ax[1][0]) ax[1][1] = fig.add_subplot(2,2,4, sharey=ax[1][0]) ax[0][1] = fig.add_subplot(2,2,2, sharex=ax[1][1], sharey=ax[0][0]) plt.subplots_adjust(hspace=0, wspace=0) # 调整子图位置 old_pos = list(ax[0][0].get_position().bounds) old_pos2 = list(ax[1][1].get_position().bounds) old_pos3 = list(ax[1][0].get_position().bounds) old_pos4 = list(ax[0][1].get_position().bounds) old_pos[-1] /= 2 old_pos2[-2] /= 2 old_pos3[-1] = old_pos3[-2] old_pos4[-1] /= 2 old_pos4[-2] /= 2 ax[0][0].set_position(old_pos) ax[1][1].set_position(old_pos2) ax[1][0].set_position(old_pos3) ax[0][1].set_position(old_pos4) # 隐藏多余坐标轴 ax[0][0].xaxis.set_visible(False) ax[0][1].xaxis.set_visible(False) ax[1][1].yaxis.set_visible(False) ax[0][1].yaxis.set_visible(False) # 适配标题位置 plt.tight_layout(rect=[0, 0, 1, 0.95]) plt.suptitle('Test') plt.show()
内容的提问来源于stack exchange,提问作者samman
相关产品推荐
相关产品推荐

