备注
前往结尾 以下载完整示例代码。
坐标轴方框比例#
这个演示展示了如何通过 set_box_aspect 直接设置 Axes 盒子的纵横比。盒子纵横比是 Axes 高度和 Axes 宽度在物理单位中的比例,与数据限制无关。这对于例如生成一个与包含的数据无关的方形图,或者在具有固定(数据)纵横比的图像旁边生成一个具有相同轴尺寸的常规图非常有用。
以下列出了 set_box_aspect 的几个使用案例。
一个正方形的 Axes,与数据无关#
无论数据限制如何,生成一个正方形的 Axes。
import matplotlib.pyplot as plt
import numpy as np
fig1, ax = plt.subplots()
ax.set_xlim(300, 400)
ax.set_box_aspect(1)
plt.show()

方形双轴#
生成一个正方形的 Axes,并带有一个双 Axes。双 Axes 继承了父 Axes 的框方面。
fig3, ax = plt.subplots()
ax2 = ax.twinx()
ax.plot([0, 10])
ax2.plot([12, 10])
ax.set_box_aspect(1)
plt.show()

普通图表与图像并列#
当使用固定数据纵横比创建图像绘图,并且默认使用 adjustable="box" 时,旁边的普通绘图的Axes高度会不相等。set_box_aspect 提供了一个简单的解决方案,通过允许普通绘图的Axes使用图像的尺寸作为盒子的纵横比。
这个例子还展示了 constrained layout 与固定盒子纵横比的良好互动。
fig4, (ax, ax2) = plt.subplots(ncols=2, layout="constrained")
np.random.seed(19680801) # Fixing random state for reproducibility
im = np.random.rand(16, 27)
ax.imshow(im)
ax2.plot([23, 45])
ax2.set_box_aspect(im.shape[0]/im.shape[1])
plt.show()

方形接头/边缘图#
在联合数据图旁边显示边缘分布可能是可取的。以下代码创建了一个方形图,其中边缘Axes的框比例与gridspec的宽度和高度比例相等。这确保了所有Axes完美对齐,无论图形的大小如何。
fig5, axs = plt.subplots(2, 2, sharex="col", sharey="row",
gridspec_kw=dict(height_ratios=[1, 3],
width_ratios=[3, 1]))
axs[0, 1].set_visible(False)
axs[0, 0].set_box_aspect(1/3)
axs[1, 0].set_box_aspect(1)
axs[1, 1].set_box_aspect(3/1)
np.random.seed(19680801) # Fixing random state for reproducibility
x, y = np.random.randn(2, 400) * [[.5], [180]]
axs[1, 0].scatter(x, y)
axs[0, 0].hist(x)
axs[1, 1].hist(y, orientation="horizontal")
plt.show()

使用box aspect设置数据方面#
在设置框的纵横比时,仍然可以设置数据纵横比。这里我们创建一个Axes,其框的长度是高度的两倍,并为其内容使用“相等”的数据纵横比,即圆实际上保持圆形。
fig6, ax = plt.subplots()
ax.add_patch(plt.Circle((5, 3), 1))
ax.set_aspect("equal", adjustable="datalim")
ax.set_box_aspect(0.5)
ax.autoscale()
plt.show()

许多子图的盒子比例#
可以在初始化时将方框纵横比传递给 Axes。以下代码创建了一个 2x3 的子图网格,所有 Axes 都是正方形的。
fig7, axs = plt.subplots(2, 3, subplot_kw=dict(box_aspect=1),
sharex=True, sharey=True, layout="constrained")
for i, ax in enumerate(axs.flat):
ax.scatter(i % 3, -((i // 3) - 0.5)*200, c=[plt.cm.hsv(i / 6)], s=300)
plt.show()
