编码快捷方式#

Matplotlib 的主要通用 API 是 Axes(坐标轴)接口。虽然它结构清晰且功能强大,但有时会显得过于冗长,编写起来比较繁琐。本页面收集了一些用于简化基于 Axes 的 API 代码的模式,旨在通过更少的代码量实现同样的绘图效果。

注意

pyplot 接口是一种更加紧凑的替代接口,其历史建模参考了 MATLAB。对于希望使用它的用户来说,这仍然是一种有效的方法。然而,它的缺点在于其简洁性依赖于一些必须理解的隐式假设。

由于遵循不同的范式,如果在代码开发过程中发现 pyplot 的灵活性不足,需要从 Axes 接口切换到 pyplot 接口,或者反之,就需要进行思维模式的转换并重写部分代码。

本教程将反其道而行之,从标准的冗长 Axes 接口开始,利用其特性在不需要通用性的情况下实现快捷操作。

假设我们想绘制一张伦敦全年每日日照时数的图表。

使用 Axes 接口的标准方法如下所示。

import matplotlib.pyplot as plt
import numpy as np

day = np.arange(365)
hours = 4.276 * np.sin(2 * np.pi * (day - 80)/365) + 12.203

fig, ax = plt.subplots()
ax.plot(day, hours, color="orange")
ax.set_xlabel("day")
ax.set_ylabel("daylight hours")
ax.set_title("London")
plt.show()
London

请注意,我们在代码中包含了 plt.show()。这是在命令行或 Python 脚本中运行代码时显示绘图窗口所必需的。如果你在运行 Jupyter Notebook,该命令会在每个单元格末尾自动执行。

在本教程的其余部分,为了简洁起见,我们将假设在 Notebook 环境中运行并省略此命令。根据你的实际使用场景,你可能仍然需要它。

如果你希望将图形保存到文件,请使用 fig.savefig("daylight.png")

将 Axes 属性汇总到单个 set() 调用中#

Matplotlib Artist(绘图对象)的属性可以通过各自的 set_*() 方法进行修改。此外,Artist 对象还有一个通用的 set() 方法,它接受关键字参数,等同于调用所有对应的 set_*() 方法。

ax.set_xlabel("day")
ax.set_ylabel("daylight hours")

也可以写成

ax.set(xlabel="day", ylabel="daylight hours")

这是你可以实现的最简单有效的代码精简。通过这种方式,我们可以将上述绘图代码缩短为

fig, ax = plt.subplots()
ax.plot(day, hours, color="orange")
ax.set(xlabel="day", ylabel="daylight hours", title="London")
London

只要你只需要为 set_*() 函数传递一个参数,这种方法就有效。如果你需要更多控制(例如 set_title("London", fontsize=16)),则仍然需要使用单独的函数。

不存储对 figure 的引用#

fig, ax = plt.subplots() 的另一个麻烦之处在于,你总是会创建一个 fig 变量,即使你并没有用到它。一个稍短的版本是使用 Python 中用于忽略值的标准变量(_):_, ax = plt.subplots()。不过,这只是稍微好一点。

你可以通过将图形(figure)和 Axes 的创建分离开来并进行链式调用来规避这个问题

ax = plt.figure().add_subplot()

这种写法在逻辑上更清晰,并且还有一个微小的优势,即你可以在内联设置图形属性;例如 plt.figure(facecolor="lightgoldenrod")。但它的缺点是比 fig, ax = plt.subplots() 更长。

如果需要,你仍然可以从 Axes 中获取 figure,例如

ax.figure.savefig("daylight_hours.png")

示例代码现在看起来如下所示

ax = plt.figure().add_subplot()
ax.plot(day, hours, color="orange")
ax.set(xlabel="day", ylabel="daylight hours", title="London")
London

在创建 Axes 时定义 Axes 属性#

set_* 方法以及 set 方法都会修改已有的对象。或者,你也可以在创建时直接定义它们。由于在 Matplotlib 中,你通常不会自己实例化类,而是调用某个工厂函数来创建对象并正确连接到绘图上,所以这看起来可能不太直观。但实际上,你只需要将所需的属性传递给工厂函数即可。你可能在不知不觉中已经在某些地方这样做了。考虑创建线条的函数

ax.plot(x, y, color="orange")

这等同于

line, = ax.plot(x, y)
line.set_color("orange")

同样的做法也可以用于创建 Axes 的函数。

ax = plt.figure().add_subplot(xlabel="day", ylabel="daylight hours", title="London")
ax.plot(day, hours, color="orange")
London

重要

Axes 属性仅作为关键字参数被 Figure.add_subplot 接受,该函数用于创建一个单独的 Axes。

对于 Figure.subplotspyplot.subplots,你需要通过关键字参数 subplot_kw 以字典形式传递这些属性。这里的限制是这些参数会应用到所有的 Axes 上。例如,如果你需要两个具有不同标签的子图(fig, (ax1, ax2) = plt.subplots(1, 2)),则必须单独设置它们。

在创建时定义 Axes 属性最适用于单个子图,或者当所有子图共享相同属性时使用。

使用隐式图形创建#

你可以更进一步,利用 pyplot 的逻辑,使用 pyplot.axes 来创建 axes

ax = plt.axes(xlabel="day", ylabel="daylight hours", title="London")
ax.plot(day, hours, color="orange")
London

警告

使用这种方法时,必须注意 pyplot 的隐式图形语义。plt.axes() 仅在没有图形存在时才会创建一个新图形。否则,它会将 Axes 添加到当前已有的图形中,这可能不是你想要的结果。

不存储对 Axes 的引用#

如果你只需要可视化一个数据集,可以直接将绘图命令附加到 Axes 的创建之后。这在 Notebook 中非常有用,当你想要创建带有配置的图表,同时希望尽量减少干扰性代码时

plt.axes(xlabel="day", ylabel="daylight hours").plot(day, hours, color="orange")
coding shortcuts

脚本总运行时间:(0 分 2.255 秒)

由 Sphinx-Gallery 生成的画廊