注意
转到末尾下载完整的示例代码。
Artist 教程#
使用 Artist 对象在画布上渲染。
Matplotlib API 分为三个层。
matplotlib.backend_bases.FigureCanvas是绘制图形的区域matplotlib.backend_bases.Renderer是知道如何在matplotlib.backend_bases.FigureCanvas上绘图的对象而
matplotlib.artist.Artist是知道如何使用渲染器在画布上绘制的对象。
matplotlib.backend_bases.FigureCanvas 和 matplotlib.backend_bases.Renderer 处理与 wxPython 等用户界面工具包通信或与 PostScript® 等绘图语言通信的所有细节,而 Artist 处理所有高级构造,如表示和布局图形、文本和线条。典型用户将 95% 的时间花在处理 Artists 上。
Artists 有两种类型:原始类型和容器类型。原始类型表示我们想要绘制到画布上的标准图形对象:Line2D、Rectangle、Text、AxesImage 等,而容器类型是放置它们的地方(Axis、Axes 和 Figure)。标准用法是创建一个 Figure 实例,使用该 Figure 创建一个或多个 Axes 实例,并使用 Axes 实例的辅助方法创建原始类型。在下面的示例中,我们使用 matplotlib.pyplot.figure() 创建一个 Figure 实例,这是一个方便的方法,用于实例化 Figure 实例并将其与您的用户界面或绘图工具包的 FigureCanvas 连接。正如我们将在下面讨论的那样,这并不是必需的——您可以直接使用 PostScript、PDF Gtk+ 或 wxPython FigureCanvas 实例,直接实例化您的 Figures 并自行连接它们——但由于我们在此重点关注 Artist API,我们将让 pyplot 为我们处理一些细节。
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(2, 1, 1) # two rows, one column, first plot
Axes 可能是 Matplotlib API 中最重要的类,也是您大部分时间将使用的类。这是因为 Axes 是大多数对象进入的绘图区域,并且 Axes 有许多特殊的辅助方法(plot()、text()、hist()、imshow())来创建最常见的图形原始类型(分别为 Line2D、Text、Rectangle、AxesImage)。这些辅助方法将获取您的数据(例如 numpy 数组和字符串),并根据需要创建原始 Artist 实例(例如 Line2D),将它们添加到相关容器中,并在请求时绘制它们。如果您想在任意位置创建 Axes,只需使用 add_axes() 方法,该方法接受一个包含 [left, bottom, width, height] 值的列表,这些值是 0-1 范围内的相对图形坐标。
fig2 = plt.figure()
ax2 = fig2.add_axes([0.15, 0.1, 0.7, 0.3])
继续我们的例子
在此示例中,ax 是上面 fig.add_subplot 调用创建的 Axes 实例,当您调用 ax.plot 时,它会创建一个 Line2D 实例并将其添加到 Axes 中。在下面的交互式 IPython 会话中,您可以看到 Axes.lines 列表的长度为 1,并且包含与 line, = ax.plot... 调用返回的相同的行。
如果您随后调用 ax.plot(且保持状态为“on”,这是默认值),则会向列表中添加额外的行。您可以通过调用其 remove 方法稍后删除一行。
Axes 还具有辅助方法,用于配置和装饰 x 轴和 y 轴的刻度、刻度标签和轴标签。
当您调用 ax.set_xlabel 时,它会将信息传递给 XAxis 的 Text 实例。每个 Axes 实例都包含一个 XAxis 和一个 YAxis 实例,它们处理刻度、刻度标签和轴标签的布局和绘制。
尝试创建下图。
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
fig.subplots_adjust(top=0.8)
ax1 = fig.add_subplot(211)
ax1.set_ylabel('Voltage [V]')
ax1.set_title('A sine wave')
t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
line, = ax1.plot(t, s, color='blue', lw=2)
# Fixing random state for reproducibility
np.random.seed(19680801)
ax2 = fig.add_axes([0.15, 0.1, 0.7, 0.3])
n, bins, patches = ax2.hist(np.random.randn(1000), 50,
facecolor='yellow', edgecolor='yellow')
ax2.set_xlabel('Time [s]')
plt.show()

自定义对象#
图中的每个元素都由一个 Matplotlib Artist 表示,每个 Artist 都有一个广泛的属性列表来配置其外观。图形本身包含一个与图形大小完全相同的 Rectangle,您可以使用它来设置图形的背景颜色和透明度。同样,每个 Axes 边界框(典型 Matplotlib 图中带有黑色边缘的标准白色框)都有一个 Rectangle 实例,该实例确定 Axes 的颜色、透明度和其它属性。这些实例作为成员变量 Figure.patch 和 Axes.patch 存储("Patch" 是从 MATLAB 继承的名称,是图形上的一块 2D "补丁"颜色,例如矩形、圆形和多边形)。每个 Matplotlib Artist 都具有以下属性:
属性 |
描述 |
|---|---|
alpha |
透明度 - 0-1 之间的标量 |
animated |
一个布尔值,用于方便动画绘制 |
坐标轴 |
Artist 所属的 Axes,可能为 None |
clip_box |
剪裁 Artist 的边界框 |
clip_on |
是否启用剪裁 |
clip_path |
Artist 被剪裁到的路径 |
contains |
一个选择函数,用于测试 Artist 是否包含选择点 |
figure |
Artist 所属的 Figure 实例,可能为 None |
label |
文本标签(例如,用于自动标记) |
picker |
控制对象选择的 Python 对象 |
transform |
变换 |
visible |
一个布尔值,表示是否应绘制 Artist |
zorder |
一个数字,确定绘制顺序 |
rasterized |
布尔值;将矢量图转为栅格图(用于压缩和 EPS 透明度) |
每个属性都通过老式的 setter 或 getter 访问(是的,我们知道这会惹恼 Pythonista,我们计划支持通过属性或特性直接访问,但尚未实现)。例如,将当前 alpha 值乘以一半:
a = o.get_alpha()
o.set_alpha(0.5*a)
如果您想同时设置多个属性,也可以使用带有关键字参数的 set 方法。例如:
o.set(alpha=0.5, zorder=2)
如果您在 Python shell 中进行交互式操作,检查 Artist 属性的一种便捷方式是使用 matplotlib.artist.getp() 函数(在 pyplot 中直接使用 getp()),它会列出属性及其值。这适用于从 Artist 派生的类,例如 Figure 和 Rectangle。以下是上面提到的 Figure 矩形属性:
In [149]: matplotlib.artist.getp(fig.patch)
agg_filter = None
alpha = None
animated = False
antialiased or aa = False
bbox = Bbox(x0=0.0, y0=0.0, x1=1.0, y1=1.0)
capstyle = butt
children = []
clip_box = None
clip_on = True
clip_path = None
contains = None
data_transform = BboxTransformTo( TransformedBbox( Bbox...
edgecolor or ec = (1.0, 1.0, 1.0, 1.0)
extents = Bbox(x0=0.0, y0=0.0, x1=640.0, y1=480.0)
facecolor or fc = (1.0, 1.0, 1.0, 1.0)
figure = Figure(640x480)
fill = True
gid = None
hatch = None
height = 1
in_layout = False
joinstyle = miter
label =
linestyle or ls = solid
linewidth or lw = 0.0
patch_transform = CompositeGenericTransform( BboxTransformTo( ...
path = Path(array([[0., 0.], [1., 0.], [1.,...
path_effects = []
picker = None
rasterized = None
sketch_params = None
snap = None
transform = CompositeGenericTransform( CompositeGenericTra...
transformed_clip_path_and_affine = (None, None)
url = None
verts = [[ 0. 0.] [640. 0.] [640. 480.] [ 0. 480....
visible = True
width = 1
window_extent = Bbox(x0=0.0, y0=0.0, x1=640.0, y1=480.0)
x = 0
xy = (0, 0)
y = 0
zorder = 1
所有类的 docstrings 也包含 Artist 属性,因此您可以查阅交互式“help”或 matplotlib.artist 以获取给定对象的属性列表。
对象容器#
现在我们知道如何检查和设置要配置的给定对象的属性,我们需要知道如何获取该对象。如引言中所述,对象有两种:原始类型和容器类型。原始类型通常是您想要配置的事物(Text 实例的字体,Line2D 的宽度),尽管容器也有一些属性——例如 Axes Artist 是一个容器,它包含图中许多原始类型,但它也有诸如 xscale 之类的属性来控制 x 轴是“线性”还是“对数”。在本节中,我们将回顾各种容器对象如何存储您想要访问的 Artists。
Figure 容器#
顶层容器 Artist 是 matplotlib.figure.Figure,它包含图形中的所有内容。图形的背景是一个 Rectangle,存储在 Figure.patch 中。当您向图形添加子图(add_subplot())和 Axes(add_axes())时,它们将被添加到 Figure.axes 中。这些方法也会返回它们创建的对象。
In [156]: fig = plt.figure()
In [157]: ax1 = fig.add_subplot(211)
In [158]: ax2 = fig.add_axes([0.1, 0.1, 0.7, 0.3])
In [159]: ax1
Out[159]: <Axes:>
In [160]: print(fig.axes)
[<Axes:>, <matplotlib.axes._axes.Axes object at 0x7f0768702be0>]
因为图形维护着“当前 Axes”的概念(参见 Figure.gca 和 Figure.sca),以支持 pylab/pyplot 状态机,所以您不应直接从 Axes 列表中插入或删除 Axes,而是使用 add_subplot() 和 add_axes() 方法进行插入,使用 Axes.remove 方法进行删除。但是,您可以自由地遍历 Axes 列表或通过索引访问您想要自定义的 Axes 实例。下面是一个示例,它打开所有 Axes 的网格:
Figure 也有自己的 images、lines、patches 和 text 属性,您可以直接使用它们添加原始类型。这样做时,Figure 的默认坐标系将简单地是像素(这通常不是您想要的)。如果您改为使用 Figure 级别的方法添加 Artist(例如,使用 Figure.text 添加文本),则默认坐标系将是“图形坐标”,其中 (0, 0) 是图形的左下角,(1, 1) 是图形的右上角。
与所有 Artist 一样,您可以通过设置 transform 属性来控制此坐标系。您可以通过将 Artist transform 设置为 fig.transFigure 来显式使用“图形坐标”。
import matplotlib.lines as lines
fig = plt.figure()
l1 = lines.Line2D([0, 1], [0, 1], transform=fig.transFigure, figure=fig)
l2 = lines.Line2D([0, 1], [1, 0], transform=fig.transFigure, figure=fig)
fig.lines.extend([l1, l2])
plt.show()

以下是 Figure 包含的 Artists 的摘要:
Axes 容器#
matplotlib.axes.Axes 是 Matplotlib 宇宙的中心——它包含了图中绝大多数的 Artists,并提供了许多辅助方法来创建并将这些 Artists 添加到自身,以及辅助方法来访问和自定义它所包含的 Artists。像 Figure 一样,它包含一个 Patch matplotlib.axes.Axes.patch,对于笛卡尔坐标系它是一个 Rectangle,对于极坐标系它是一个 Circle;这个补丁决定了绘图区域的形状、背景和边框。
ax = fig.add_subplot()
rect = ax.patch # a Rectangle instance
rect.set_facecolor('green')
当您调用绘图方法时,例如典型的 plot 并传入数组或值列表,该方法将创建一个 matplotlib.lines.Line2D 实例,使用所有作为关键字参数传入的 Line2D 属性更新该线条,将该线条添加到 Axes 中,并将其返回给您。
plot 返回一个线条列表,因为您可以传入多个 x、y 对进行绘图,我们将长度为 1 的列表的第一个元素解包到 line 变量中。这条线已被添加到 Axes.lines 列表中。
In [229]: print(ax.lines)
[<matplotlib.lines.Line2D at 0xd378b0c>]
同样,创建补丁的方法,如 bar() 创建一个矩形列表,会将这些补丁添加到 Axes.patches 列表中。
您不应直接将对象添加到 Axes.lines 或 Axes.patches 列表中,因为 Axes 在创建和添加对象时需要做一些事情:
它设置了
Artist的figure和axes属性;它设置默认的
Axes变换(除非已设置);它检查
Artist中包含的数据,以更新控制自动缩放的数据结构,以便调整视图限制以包含绘制的数据。
尽管如此,您仍然可以自己创建对象并使用辅助方法(如 add_line 和 add_patch)直接将它们添加到 Axes。下面是一个带有注释的交互式会话,说明了正在发生的事情:
In [262]: fig, ax = plt.subplots()
# create a rectangle instance
In [263]: rect = matplotlib.patches.Rectangle((1, 1), width=5, height=12)
# by default the Axes instance is None
In [264]: print(rect.axes)
None
# and the transformation instance is set to the "identity transform"
In [265]: print(rect.get_data_transform())
IdentityTransform()
# now we add the Rectangle to the Axes
In [266]: ax.add_patch(rect)
# and notice that the ax.add_patch method has set the Axes
# instance
In [267]: print(rect.axes)
Axes(0.125,0.1;0.775x0.8)
# and the transformation has been set too
In [268]: print(rect.get_data_transform())
CompositeGenericTransform(
TransformWrapper(
BlendedAffine2D(
IdentityTransform(),
IdentityTransform())),
CompositeGenericTransform(
BboxTransformFrom(
TransformedBbox(
Bbox(x0=0.0, y0=0.0, x1=1.0, y1=1.0),
TransformWrapper(
BlendedAffine2D(
IdentityTransform(),
IdentityTransform())))),
BboxTransformTo(
TransformedBbox(
Bbox(x0=0.125, y0=0.10999999999999999, x1=0.9, y1=0.88),
BboxTransformTo(
TransformedBbox(
Bbox(x0=0.0, y0=0.0, x1=6.4, y1=4.8),
Affine2D(
[[100. 0. 0.]
[ 0. 100. 0.]
[ 0. 0. 1.]])))))))
# the default Axes transformation is ax.transData
In [269]: print(ax.transData)
CompositeGenericTransform(
TransformWrapper(
BlendedAffine2D(
IdentityTransform(),
IdentityTransform())),
CompositeGenericTransform(
BboxTransformFrom(
TransformedBbox(
Bbox(x0=0.0, y0=0.0, x1=1.0, y1=1.0),
TransformWrapper(
BlendedAffine2D(
IdentityTransform(),
IdentityTransform())))),
BboxTransformTo(
TransformedBbox(
Bbox(x0=0.125, y0=0.10999999999999999, x1=0.9, y1=0.88),
BboxTransformTo(
TransformedBbox(
Bbox(x0=0.0, y0=0.0, x1=6.4, y1=4.8),
Affine2D(
[[100. 0. 0.]
[ 0. 100. 0.]
[ 0. 0. 1.]])))))))
# notice that the xlimits of the Axes have not been changed
In [270]: print(ax.get_xlim())
(0.0, 1.0)
# but the data limits have been updated to encompass the rectangle
In [271]: print(ax.dataLim.bounds)
(1.0, 1.0, 5.0, 12.0)
# we can manually invoke the auto-scaling machinery
In [272]: ax.autoscale_view()
# and now the xlim are updated to encompass the rectangle, plus margins
In [273]: print(ax.get_xlim())
(0.75, 6.25)
# we have to manually force a figure draw
In [274]: fig.canvas.draw()
Axes 有许多许多辅助方法,用于创建原始 Artists 并将它们添加到各自的容器中。下表总结了其中的一小部分,它们创建的 Artist 类型,以及它们存储的位置:
Axes 辅助方法 |
Artist |
容器 |
|---|---|---|
|
ax.texts |
|
|
ax.patches |
|
|
ax.lines 和 ax.patches |
|
|
ax.patches |
|
|
ax.patches |
|
|
ax.images |
|
|
ax.get_legend() |
|
|
ax.lines |
|
|
ax.collections |
|
|
ax.texts |
除了所有这些 Artists 之外,Axes 还包含两个重要的 Artist 容器:XAxis 和 YAxis,它们处理刻度和标签的绘制。它们作为实例变量 matplotlib.axes.Axes.xaxis 和 matplotlib.axes.Axes.yaxis 存储。下面将详细介绍 XAxis 和 YAxis 容器,但请注意,Axes 包含许多辅助方法,这些方法将调用转发给 Axis 实例,因此您通常无需直接与它们交互,除非您想这样做。例如,您可以使用 Axes 辅助方法设置 XAxis 刻度标签的字体颜色:
下面是 Axes 包含的 Artists 的摘要:
Axes 属性 |
描述 |
|---|---|
artists |
一个 |
patch |
用于 Axes 背景的 |
collections |
一个 |
images |
一个 |
lines |
一个 |
patches |
一个 |
texts |
一个 |
xaxis |
一个 |
yaxis |
一个 |
图例可以通过 get_legend 访问。
Axis 容器#
matplotlib.axis.Axis 实例处理刻度线、网格线、刻度标签和轴标签的绘制。您可以分别为 y 轴配置左右刻度,分别为 x 轴配置上下刻度。Axis 还存储了用于自动缩放、平移和缩放的数据和视图间隔,以及控制刻度位置和字符串表示的 Locator 和 Formatter 实例。
每个 Axis 对象都包含一个 label 属性(这是 pyplot 在调用 xlabel 和 ylabel 时修改的信息),以及一个主刻度列表和次刻度列表。刻度是 axis.XTick 和 axis.YTick 实例,它们包含实际的线条和文本原始类型,用于渲染刻度及其标签。由于刻度是根据需要动态创建的(例如,在平移和缩放时),您应该通过其访问器方法 axis.Axis.get_major_ticks 和 axis.Axis.get_minor_ticks 访问主刻度列表和次刻度列表。虽然刻度包含所有原始类型并将在下面介绍,但 Axis 实例具有返回刻度线、刻度标签、刻度位置等的访问器方法。
fig, ax = plt.subplots()
axis = ax.xaxis
axis.get_ticklocs()

array([0. , 0.2, 0.4, 0.6, 0.8, 1. ])
[Text(0.0, 0, '0.0'), Text(0.2, 0, '0.2'), Text(0.4, 0, '0.4'), Text(0.6000000000000001, 0, '0.6'), Text(0.8, 0, '0.8'), Text(1.0, 0, '1.0')]
请注意,刻度线的数量是标签的两倍,因为默认情况下顶部和底部都有刻度线,但只有 x 轴下方有刻度标签;但是,这可以自定义。
<a list of 12 Line2D ticklines objects>
使用上述方法,默认情况下您只会获得主刻度列表,但您也可以请求次刻度:
axis.get_ticklabels(minor=True)
axis.get_ticklines(minor=True)
<a list of 0 Line2D ticklines objects>
以下是 Axis 的一些有用访问器方法的摘要(这些方法在有用时都有相应的 setter,例如 set_major_formatter()。)
Axis 访问器方法 |
描述 |
|---|---|
轴的比例,例如“log”或“linear” |
|
轴视图限制的区间实例 |
|
轴数据限制的区间实例 |
|
轴的网格线列表 |
|
轴标签 - 一个 |
|
轴偏移文本 - 一个 |
|
一个 |
|
一个 |
|
刻度位置列表 - 关键字 minor=True|False |
|
主刻度的 |
|
主刻度的 |
|
次刻度的 |
|
次刻度的 |
|
主刻度的 |
|
次刻度的 |
|
打开或关闭主刻度或次刻度的网格 |
这是一个自定义 Axes 和 Tick 属性的示例,尽管其美观性不值得推荐。
# plt.figure creates a matplotlib.figure.Figure instance
fig = plt.figure()
rect = fig.patch # a rectangle instance
rect.set_facecolor('lightgoldenrodyellow')
ax1 = fig.add_axes([0.1, 0.3, 0.4, 0.4])
rect = ax1.patch
rect.set_facecolor('lightslategray')
for label in ax1.xaxis.get_ticklabels():
# label is a Text instance
label.set_color('red')
label.set_rotation(45)
label.set_fontsize(16)
for line in ax1.yaxis.get_ticklines():
# line is a Line2D instance
line.set_color('green')
line.set_markersize(25)
line.set_markeredgewidth(3)
plt.show()

Tick 容器#
matplotlib.axis.Tick 是我们从 Figure 到 Axes 再到 Axis 最后到 Tick 的下降过程中最后一个容器对象。Tick 包含刻度和网格线实例,以及上下刻度的标签实例。这些都可以直接作为 Tick 的属性访问。
Tick 属性 |
描述 |
|---|---|
tick1line |
一个 |
tick2line |
一个 |
gridline |
一个 |
label1 |
一个 |
label2 |
一个 |
这是一个示例,它为右侧刻度设置了美元符号格式器,并将其在 y 轴的右侧着色为绿色。
import matplotlib.pyplot as plt
import numpy as np
# Fixing random state for reproducibility
np.random.seed(19680801)
fig, ax = plt.subplots()
ax.plot(100*np.random.rand(20))
# Use automatic StrMethodFormatter
ax.yaxis.set_major_formatter('${x:1.2f}')
ax.yaxis.set_tick_params(which='major', labelcolor='green',
labelleft=False, labelright=True)
plt.show()

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