Matplotlib子图中实现跨双轴的Y轴标签与顶部轴Y轴标签对齐
Matplotlib子图中实现跨双轴的Y轴标签与顶部轴Y轴标签对齐
我最近遇到了一个Matplotlib子图布局的小难题,想请教大家怎么解决:我做了一个包含3个子图的绘图,顶部子图的高度是下面两个的两倍,所有子图的X、Y轴含义完全一致。但因为Y轴标签比较长,下面两个子图的Y轴标签直接重叠在了一起,效果如下:
import numpy as np import matplotlib.pyplot as plt from matplotlib.transforms import blended_transform_factory imgs = [ np.random.randn(200, 200), np.random.randn(50, 70), np.random.randn(100, 100), ] figsize = [4, 6] ylabel = "Long label for radius (cm)" fig = plt.figure(figsize=figsize, layout="constrained") gs = fig.add_gridspec(3, 1, height_ratios=[2, 1, 1]) axes = [fig.add_subplot(gs[i]) for i in range(3)] for i in range(len(axes)): ax = axes[i] ax.imshow(imgs[i], aspect="auto") ax.set_xlabel("time (min)") # 以下是初始的标签设置逻辑 for ax in axes: ax.set_ylabel(ylabel) fig.align_ylabels(axes) # 因为不同子图Y轴刻度数量不同,必须加这个来对齐刻度

我的目标是让下面两个子图共用一个Y轴标签,或者至少让它们的Y轴标签和顶部子图的Y轴标签在X方向完全对齐。我试了好几种方法,都没达到理想效果:
第一种尝试
我给顶部子图正常设置标签,给第二个子图把标签位置设为底部:
axes[0].set_ylabel(ylabel) axes[1].set_ylabel(ylabel, loc="bottom") fig.align_ylabels(axes)

这次X方向的对齐是对的,但Y轴标签的位置明显不对,太靠下了,完全没和下面两个子图的中间对齐。
第二种尝试
我给第二个子图的标签加了垂直居中的参数:
axes[0].set_ylabel(ylabel) axes[1].set_ylabel(ylabel, loc="bottom", va="center") fig.align_ylabels(axes)

结果更糟,X和Y方向的对齐都出了问题,标签直接歪到一边去了。
第三种尝试
我尝试用混合变换来调整标签的位置:
axes[0].set_ylabel(ylabel) axes[1].set_ylabel(ylabel) ax = axes[1] new_trafo = blended_transform_factory( x_transform=ax.yaxis.label.get_transform(), y_transform=ax.transAxes, ) axes[1].set_ylabel(ylabel, y=0.0, va="center") fig.align_ylabels(axes)

这次Y轴位置勉强能看,但X方向的对齐还是错的,和顶部标签不在一条垂直线上。
我的核心需求
我想要的是下面两个子图共用一个Y轴标签,或者至少让它们的标签和顶部的标签在X方向完全对齐,就像这个理想效果一样:
补充说明几点:
- 我需要纯Matplotlib的解决方案,不想导出成SVG后再手动编辑;
- 把下面两个子图的标签拆成两行也不行,因为这样会让顶部子图的Y轴标签和旁边的轴之间产生多余空隙——实际场景里顶部子图左边还有其他轴,效果如下:
axes[0].set_ylabel(ylabel) for ax in axes[1:]: ax.set_ylabel("Long label\nfor radius (cm)") fig.align_ylabels(axes)

备注:内容来源于stack exchange,提问作者Niklas Netter
相关产品推荐
相关产品推荐

