Axes(或子图)简介#

Matplotlib Axes 是创建数据可视化的入口。一旦在图形上放置了 Axes,就可以使用许多方法向 Axes 添加数据。Axes 通常有一对 Axis 艺术家,它们定义了数据坐标系,并包含添加注释的方法,如 x 轴和 y 轴标签、标题和图例。

../../../_images/anatomy.png

图的结构#

在上图中,Axes 对象是通过 ax = fig.subplots() 创建的。图上的其他所有内容都是通过这个 ax 对象的方法创建的,或者可以从它访问。如果我们想更改 x 轴的标签,我们调用 ax.set_xlabel('New Label'),如果我们想绘制一些数据,我们调用 ax.plot(x, y)。实际上,在上图中,唯一不属于 Axes 的 Artist 是 Figure 本身,因此 axes.Axes 类确实是访问 Matplotlib 大部分功能的关键。

需要注意的是,Axes 对于 Matplotlib 的操作是如此基础,以至于这里的大量内容与 快速开始 中的内容重复。

创建坐标轴#

import matplotlib.pyplot as plt
import numpy as np

fig, axs = plt.subplots(ncols=2, nrows=2, figsize=(3.5, 2.5),
                        layout="constrained")
# for each Axes, add an artist, in this case a nice label in the middle...
for row in range(2):
    for col in range(2):
        axs[row, col].annotate(f'axs[{row}, {col}]', (0.5, 0.5),
                            transform=axs[row, col].transAxes,
                            ha='center', va='center', fontsize=18,
                            color='darkgrey')
fig.suptitle('plt.subplots()')

(Source code, 2x.png, png)

可以通过 Figure 对象的方法或 pyplot 接口添加轴。这些方法在 创建图表在图形中排列多个轴 中有更详细的讨论。然而,例如 add_axes 会手动在页面上定位一个轴。在上面的例子中,subplots 在图上放置了一个子图网格,而 axs 是一个 (2, 2) 的 Axes 数组,每个轴都可以添加数据。

有多种其他方法可以将 Axes 添加到 Figure 中:

  • Figure.add_axes: 手动定位一个 Axes。fig.add_axes([0, 0, 1, 1]) 创建一个填充整个图形的 Axes。

  • pyplot.subplotsFigure.subplots:如上例所示,添加一个 Axes 网格。pyplot 版本返回 Figure 对象和 Axes 数组。注意,fig, ax = plt.subplots() 向 Figure 添加一个 Axes。

  • pyplot.subplot_mosaicFigure.subplot_mosaic:添加一个命名 Axes 的网格并返回一个 Axes 字典。对于 fig, axs = plt.subplot_mosaic([['left', 'right'], ['bottom', 'bottom']])axs['left'] 是位于顶部行左侧的 Axes,而 axs['bottom'] 是位于底部且跨越两列的 Axes。

有关如何在图形上排列轴网格的更多详细信息,请参阅 在图形中排列多个轴

坐标轴绘图方法#

大多数高级绘图方法都可以从 axes.Axes 类中访问。请参阅 API 文档以获取完整精选列表,以及 图表类型 以获取示例。一个基本示例是 axes.Axes.plot

fig, ax = plt.subplots(figsize=(4, 3))
np.random.seed(19680801)
t = np.arange(100)
x = np.cumsum(np.random.randn(100))
lines = ax.plot(t, x)

(Source code, 2x.png, png)

注意 plot 返回一个 lines 艺术家的列表,这些艺术家可以随后被操作,如在 艺术家介绍 中讨论的那样。

以下是一个非常不完整的绘图方法列表。再次提醒,更多示例请参见 图表类型,完整方法列表请参见 axes.Axes

基本图表

plot, scatter, bar, step

数组

pcolormesh, contour, quiver, streamplot, imshow

统计图表

hist, errorbar, hist2d, pie, boxplot, violinplot

非结构化图表

tricontour, tripcolor

坐标轴标签和注释#

通常我们希望用 xlabel、ylabel 和 title 来标注 Axes,并且经常我们希望有一个图例来区分不同的绘图元素。Axes 类提供了多种方法来创建这些注释。

fig, ax = plt.subplots(figsize=(5, 3), layout='constrained')
np.random.seed(19680801)
t = np.arange(200)
x = np.cumsum(np.random.randn(200))
y = np.cumsum(np.random.randn(200))
linesx = ax.plot(t, x, label='Random walk x')
linesy = ax.plot(t, y, label='Random walk y')

ax.set_xlabel('Time [s]')
ax.set_ylabel('Distance [km]')
ax.set_title('Random walk example')
ax.legend()

(Source code, 2x.png, png)

这些方法相对直接,尽管可以在文本对象上设置许多 文本属性和布局,如 fontsizefontnamehorizontalalignment。图例可以复杂得多;更多详情请参见 图例指南

注意,文本也可以使用 textannotate 添加到坐标轴中。这可以非常复杂:更多信息请参见 文本属性和布局注解

坐标轴的限制、刻度和标记#

每个 Axes 有两个(或更多) Axis 对象,可以通过 xaxisyaxis 属性访问。这些对象上有很多方法,对于高度可定制的 Axis 来说,阅读 Axis 的 API 非常有用。然而,Axes 类为这些方法中最常见的方法提供了许多辅助工具。实际上,上面讨论的 set_xlabelset_label_text 的辅助工具。

其他重要方法设置轴的范围(set_xlimset_ylim),或者更根本地设置轴的刻度。因此,例如,我们可以使轴具有对数刻度,并放大数据的子部分:

fig, ax = plt.subplots(figsize=(4, 2.5), layout='constrained')
np.random.seed(19680801)
t = np.arange(200)
x = 2**np.cumsum(np.random.randn(200))
linesx = ax.plot(t, x)
ax.set_yscale('log')
ax.set_xlim([20, 180])

(Source code, 2x.png, png)

Axes 类还提供了处理轴刻度和其标签的辅助方法。最直接的是 set_xticksset_yticks,它们可以手动设置刻度位置,并可选地设置其标签。次要刻度可以通过 minorticks_onminorticks_off 来切换。

可以使用 tick_params 调整 Axes 刻度和刻度标签的许多方面。例如,要将标签放在轴的顶部而不是底部,将刻度颜色设为红色,并将刻度标签颜色设为绿色:

fig, ax = plt.subplots(figsize=(4, 2.5))
ax.plot(np.arange(10))
ax.tick_params(top=True, labeltop=True, color='red', axis='x',
               labelcolor='green')

(Source code, 2x.png, png)

在刻度、设置比例和控制轴方面,可以对这些轴级别的助手进行高度自定义,以实现更精细的控制。

Axes 布局#

有时在数据空间中设置图形的纵横比很重要,我们可以使用 set_aspect 来实现:

fig, axs = plt.subplots(ncols=2, figsize=(7, 2.5), layout='constrained')
np.random.seed(19680801)
t = np.arange(200)
x = np.cumsum(np.random.randn(200))
axs[0].plot(t, x)
axs[0].set_title('aspect="auto"')

axs[1].plot(t, x)
axs[1].set_aspect(3)
axs[1].set_title('aspect=3')

(Source code, 2x.png, png)