简介
本实验将指导你使用 Matplotlib 中的 set_box_aspect() 方法创建不同的绘图。此方法以物理单位设置坐标轴高度和宽度之间的纵横比,与数据范围无关。它对于生成正方形绘图(无论包含何种数据),或者在具有固定(数据)纵横比的图像绘图旁边放置具有相同坐标轴尺寸的常规绘图非常有用。
虚拟机使用提示
虚拟机启动完成后,点击左上角切换到 Notebook 标签页,即可访问 Jupyter Notebook 进行练习。
有时,你可能需要等待几秒钟,让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动进行。
如果你在学习过程中遇到问题,随时向 Labby 提问。学习结束后请提供反馈,我们会及时为你解决问题。
与数据无关的正方形坐标轴
无论数据范围如何,我们都将创建一个正方形的坐标轴。
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()
共享的正方形坐标轴
我们将创建大小为正方形的共享子图。
fig2, (ax, ax2) = plt.subplots(ncols=2, sharey=True)
ax.plot([1, 5], [0, 10])
ax2.plot([100, 500], [10, 15])
ax.set_box_aspect(1)
ax2.set_box_aspect(1)
plt.show()
正方形的双坐标轴
我们将创建一个带有双坐标轴的正方形坐标轴。双坐标轴会继承父坐标轴的框体纵横比。
fig3, ax = plt.subplots()
ax2 = ax.twinx()
ax.plot([0, 10])
ax2.plot([12, 10])
ax.set_box_aspect(1)
plt.show()
图像旁边的常规绘图
当在常规绘图旁边创建具有固定数据纵横比且默认 adjustable="box" 的图像绘图时,坐标轴的高度会不一致。set_box_aspect() 提供了一个简单的解决方案,允许常规绘图的坐标轴使用图像的尺寸作为框体纵横比。此示例还展示了 约束布局(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()
正方形的联合/边缘绘图
在联合数据绘图旁边展示边缘分布可能是很有用的。以下代码创建了一个正方形绘图,其中边缘坐标轴的框体纵横比等于网格布局(gridspec)的宽度和高度比例。这确保了所有坐标轴能完美对齐,而不受图形大小的影响。
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()
多个子图的框体纵横比
可以在初始化时为坐标轴(Axes)指定框体纵横比。以下代码创建了一个 2 行 3 列的子图网格,其中所有坐标轴都是正方形的。
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()
总结
本实验概述了如何在 Matplotlib 中使用 set_box_aspect() 来创建坐标轴高度和宽度之间具有固定纵横比的不同类型的绘图。