如何使Matplotlib轴的HIGH/LOW标签自动居中于对应区域?
解决Matplotlib标签自动居中的问题
一、最简方案:用文本对齐参数直接搞定
你当前代码里的问题在于,axs.text()默认把文本的左下角作为锚点定位,所以即使选了25%/75%的坐标,文本也不会居中。只需要给text()加上ha='center'(水平居中)和va='center'(垂直居中)参数,就能让文本以设置的(x,y)为中心对齐,完美匹配你要的25%/75%位置效果,代码也不用改复杂。
修改标签部分的代码:
# y轴LOW/HIGH标签 - 垂直文本,水平居中到左侧偏移位置,垂直居中到25%/75%高度 axs.text(minx - 0.5 * offsetx, 0.25 * maxy, "LOW", fontdict={}, rotation="vertical", ha='center', va='center') axs.text(minx - 0.5 * offsetx, 0.75 * maxy, "HIGH", fontdict={}, rotation="vertical", ha='center', va='center') # x轴LOW/HIGH标签 - 水平文本,垂直居中到顶部偏移位置,水平居中到25%/75%宽度 axs.text(0.25 * maxx, maxy + 0.5 * offsety, "LOW", fontdict={}, ha='center', va='center') axs.text(0.75 * maxx, maxy + 0.5 * offsety, "HIGH", fontdict={}, ha='center', va='center')
二、进阶:用Bbox实现包围盒精准居中
如果后续可能调整偏移量或图表范围,想让标签自动跟着包围盒走,可以用Bbox来定位,比如让标签完全居中在左侧竖条或顶部横条的对应区域:
from matplotlib.transforms import Bbox # 定义左侧竖条的包围盒 left_bbox = Bbox.from_extents(minx - offsetx, miny, minx, maxy) # y轴LOW标签:居中在左侧竖条下半部分 low_y = axs.text(0, 0, "LOW", rotation="vertical", ha='center', va='center') low_y.set_position([left_bbox.x0 + left_bbox.width/2, left_bbox.y0 + left_bbox.height*0.25]) # y轴HIGH标签:居中在左侧竖条上半部分 high_y = axs.text(0, 0, "HIGH", rotation="vertical", ha='center', va='center') high_y.set_position([left_bbox.x0 + left_bbox.width/2, left_bbox.y0 + left_bbox.height*0.75]) # 定义顶部横条的包围盒 top_bbox = Bbox.from_extents(minx, maxy, maxx, maxy + offsety) # x轴LOW标签:居中在顶部横条左半部分 low_x = axs.text(0, 0, "LOW", ha='center', va='center') low_x.set_position([top_bbox.x0 + top_bbox.width*0.25, top_bbox.y0 + top_bbox.height/2]) # x轴HIGH标签:居中在顶部横条右半部分 high_x = axs.text(0, 0, "HIGH", ha='center', va='center') high_x.set_position([top_bbox.x0 + top_bbox.width*0.75, top_bbox.y0 + top_bbox.height/2])
这种方式的好处是,不管怎么调offsetx、offsety或者图表大小,标签都会自动保持在对应区域的中心,不用手动改坐标。
三、完整优化代码(含隐藏默认坐标轴)
把最简方案整合进去,再加个隐藏默认坐标轴的操作,让图表更接近目标效果:
def create_my_plot(): # initialize figure fig = Figure(figsize=(7, 6)) axs = fig.subplots() minx, maxx, midx = 0, 1, 0.5 miny, maxy, midy = 0, 1, 0.5 offsetx, offsety = 0.15, 0.15 axs.add_patch(mpatches.Rectangle((minx, maxy), maxx, offsety, fill=False, edgecolor="black", clip_on=False, lw=0.5)) axs.add_patch(mpatches.Rectangle((minx, miny), -offsetx, maxy, fill=False, edgecolor="black", clip_on=False, lw=0.5)) axs.add_patch(mpatches.Rectangle((minx, midy), midx, midy, alpha=0.1, facecolor="green")) axs.add_patch(mpatches.Rectangle((midx, midy), midx, midy, alpha=0.1, facecolor="yellow")) axs.add_patch(mpatches.Rectangle((minx, miny), midx, midy, alpha=0.1, facecolor="gray")) axs.add_patch(mpatches.Rectangle((midx, miny), midx, midy, alpha=0.1, facecolor="red")) axs.add_line(Line2D(xdata=(minx-offsetx, maxx), ydata=(midy, midy), clip_on=False, color="black", lw=0.5)) axs.add_line(Line2D(xdata=(midx, midx), ydata=(miny, maxy + offsety), clip_on=False, color="black", lw=0.5)) # 优化后的标签对齐 axs.text(minx - 0.5 * offsetx, 0.25 * maxy, "LOW", fontdict={}, rotation="vertical", ha='center', va='center') axs.text(minx - 0.5 * offsetx, 0.75 * maxy, "HIGH", fontdict={}, rotation="vertical", ha='center', va='center') axs.text(0.25 * maxx, maxy + 0.5 * offsety, "LOW", fontdict={}, ha='center', va='center') axs.text(0.75 * maxx, maxy + 0.5 * offsety, "HIGH", fontdict={}, ha='center', va='center') # 隐藏默认坐标轴,让图表更干净 axs.set_xlim(minx - offsetx, maxx) axs.set_ylim(miny, maxy + offsety) axs.set_xticks([]) axs.set_yticks([]) for spine in axs.spines.values(): spine.set_visible(False) buf = BytesIO() fig.savefig(buf, format="png") data = base64.b64encode(buf.getbuffer()).decode("ascii") return f"<img src='data:image/png;base64,{data}'/>"
内容的提问来源于stack exchange,提问作者Tarquinius
相关产品推荐
相关产品推荐

