备注
前往结尾 以下载完整示例代码。
艺术家教程#
使用 Artist 对象在画布上渲染。
Matplotlib API 有三层。
the
matplotlib.backend_bases.FigureCanvas是绘制图形的区域这个
matplotlib.backend_bases.Renderer对象知道如何在FigureCanvas上绘制。而
matplotlib.artist.Artist是知道如何使用渲染器在画布上绘制的对象。
The FigureCanvas 和 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
The 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])
继续我们的示例:
import numpy as np
t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
line, = ax.plot(t, s, color='blue', lw=2)
在这个例子中,ax 是由上面的 fig.add_subplot 调用创建的 Axes 实例,当你调用 ax.plot 时,它会创建一个 Line2D 实例并将其添加到 Axes 中。在下面的交互式 IPython 会话中,你可以看到 Axes.lines 列表的长度为1,并且包含与 line, = ax.plot... 调用返回的相同的线:
In [101]: ax.lines[0]
Out[101]: <matplotlib.lines.Line2D at 0x19a95710>
In [102]: line
Out[102]: <matplotlib.lines.Line2D at 0x19a95710>
如果你对 ax.plot 进行后续调用(并且保持状态为“开启”,这是默认设置),那么将会在列表中添加额外的线条。你可以通过调用其 remove 方法来移除一条线:
line = ax.lines[0]
line.remove()
Axes 也有辅助方法来配置和装饰 x 轴和 y 轴的刻度、刻度标签和轴标签:
xtext = ax.set_xlabel('my xdata') # returns a Text instance
ytext = ax.set_ylabel('my ydata')
当你调用 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 表示,每个元素都有大量的属性来配置其外观。图本身包含一个与图大小完全相同的 Rectangle,您可以使用它来设置图的背景颜色和透明度。同样,每个 Axes 边界框(典型 Matplotlib 图中的标准白色框和黑色边缘)都有一个 Rectangle 实例,该实例决定了 Axes 的颜色、透明度和其他属性。这些实例存储为成员变量 Figure.patch 和 Axes.patch <matplotlib.axes.Axes.patch>`(“Patch”是从 MATLAB 继承的名称,是图上的 2D 颜色“补丁”,例如矩形、圆形和多边形)。每个 Matplotlib ``Artist` 都有以下属性
属性 |
描述 |
|---|---|
alpha |
透明度 - 一个从 0-1 的标量 |
动画 |
一个用于辅助动画绘制的布尔值 |
axes |
艺术家所在的轴,可能为 None |
clip_box |
裁剪艺术家的边界框 |
clip_on |
是否启用裁剪 |
clip_path |
艺术家被裁剪的路径 |
包含 |
一个拾取函数,用于测试艺术家是否包含拾取点 |
figure |
艺术家所处的图形实例,可能为 None |
标签 |
文本标签(例如,用于自动标记) |
选择器 |
一个控制对象拾取的Python对象 |
变换 |
变换 |
可见的 |
一个布尔值,指示是否应绘制艺术家 |
zorder |
一个决定绘制顺序的数字 |
栅格化 |
布尔值;将矢量转换为光栅图形(用于压缩和EPS透明度) |
每个属性都通过传统的 setter 或 getter 来访问(是的,我们知道这会让 Python 开发者感到不适,我们计划支持通过属性或特性直接访问,但目前尚未实现)。例如,要将当前的 alpha 值乘以一半:
a = o.get_alpha()
o.set_alpha(0.5*a)
如果你想一次设置多个属性,你也可以使用带有关键字参数的 set 方法。例如:
o.set(alpha=0.5, zorder=2)
如果你在Python shell中进行交互式工作,检查``Artist``属性的一个便捷方法是使用:func:matplotlib.artist.getp`函数(在pyplot中简化为:func:`~matplotlib.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
所有类的文档字符串也包含 Artist 属性,因此您可以参考交互式“帮助”或 matplotlib.artist 以获取给定对象的属性列表。
对象容器#
既然我们已经知道如何检查和设置我们想要配置的给定对象的属性,我们需要知道如何获取该对象。如引言中所述,有两种类型的对象:原始对象和容器对象。原始对象通常是您想要配置的内容(例如 Text 实例的字体,Line2D 的宽度),尽管容器对象也有一些属性——例如 Axes Artist 是一个包含图表中许多原始对象的容器,但它也有一些属性,如 xscale 来控制 x 轴是 'linear' 还是 'log'。在本节中,我们将回顾各种容器对象存储您想要获取的 Artists 的位置。
图形容器#
顶级容器 Artist 是 matplotlib.figure.Figure,它包含了图中的所有内容。图的背景是一个 Rectangle,存储在 Figure.patch 中。当你添加子图(add_subplot())和轴(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的网格打开:
for ax in fig.axes:
ax.grid(True)
该图形还具有自己的 images、lines、patches 和 text 属性,您可以使用这些属性直接添加图元。当这样做时,Figure 的默认坐标系统将简单地以像素为单位(这通常不是您想要的)。如果您改为使用图形级方法来添加艺术家(例如,使用 Figure.text 添加文本),那么默认坐标系统将是“图形坐标”,其中 (0, 0) 是图形的左下角,(1, 1) 是图形的右上角。
与所有 Artist 一样,您可以通过设置变换属性来控制这个坐标系。您可以通过将 Artist 变换设置为 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包含的艺术家的总结
Axes 容器#
The matplotlib.axes.Axes 是 Matplotlib 宇宙的中心 -- 它包含了图表中使用的大多数 Artists,并有许多辅助方法来创建和添加这些 Artists 到自身,以及访问和自定义其包含的 Artists 的辅助方法。与 Figure 类似,它包含一个 Patch patch,对于笛卡尔坐标系这是一个 Rectangle,对于极坐标系这是一个 Circle;这个 patch 决定了绘图区域的形状、背景和边框:
ax = fig.add_subplot()
rect = ax.patch # a Rectangle instance
rect.set_facecolor('green')
当你调用一个绘图方法时,例如典型的 plot 并传入数组或值列表,该方法将创建一个 matplotlib.lines.Line2D 实例,用所有作为关键字参数传递的 Line2D 属性更新线条,将线条添加到 Axes 中,并将其返回给你:
In [213]: x, y = np.random.rand(2, 100)
In [214]: line, = ax.plot(x, y, '-', color='blue', linewidth=2)
plot 返回一个线条列表,因为你可以在绘图时传入多个 x, y 对,我们将长度为一的列表的第一个元素解包到 line 变量中。该线条已被添加到 Axes.lines 列表中:
In [229]: print(ax.lines)
[<matplotlib.lines.Line2D at 0xd378b0c>]
同样地,创建补丁的方法,如 bar() 创建一个矩形列表,会将补丁添加到 Axes.patches 列表中:
In [233]: n, bins, rectangles = ax.hist(np.random.randn(1000), 50)
In [234]: rectangles
Out[234]: <BarContainer object of 50 artists>
In [235]: print(len(ax.patches))
Out[235]: 50
你不应该直接将对象添加到 Axes.lines 或 Axes.patches 列表中,因为 Axes 在创建和添加对象时需要做一些事情:
它设置了
Artist的figure和axes属性;它设置默认的
Axes变换(除非已经设置了变换);它检查
Artist中包含的数据,以更新控制自动缩放的数据结构,从而调整视图限制以包含绘制的数据。
不过,您可以自己创建对象并将它们直接添加到 Axes 中,使用诸如 add_line 和 add_patch 等辅助方法。以下是一个注释的交互式会话,说明了正在发生的事情:
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 类型以及存储位置。
坐标轴辅助方法 |
艺术家 |
容器 |
|---|---|---|
|
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,它们负责绘制刻度和标签。这些存储为实例变量 xaxis 和 yaxis。XAxis 和 YAxis 容器将在下面详细介绍,但请注意,Axes 包含许多辅助方法,这些方法将调用转发给 Axis 实例,因此您通常不需要直接与它们打交道,除非您想这样做。例如,您可以使用 Axes 辅助方法设置 XAxis 刻度标签的字体颜色:
ax.tick_params(axis='x', labelcolor='orange')
以下是 Axes 包含的艺术家概述
Axes 属性 |
描述 |
|---|---|
艺术家 |
一个 |
补丁 |
用于 Axes 背景的 |
集合 |
|
图片 |
一个 |
行 |
一个 |
补丁 |
一个 |
|
一个 |
x轴 |
一个 |
y轴 |
一个 |
图例可以通过 get_legend 访问。
轴容器#
The 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. ])
axis.get_ticklabels()
[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轴下方有刻度标签;不过,这可以自定义。
axis.get_ticklines()
<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 的一些有用访问器方法的总结(这些方法在有用的地方有相应的设置器,例如 set_major_formatter()。)
轴访问器方法 |
描述 |
|---|---|
轴的比例,例如,'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 容器#
在从 Figure 到 Axes 再到 Axis 的下降过程中,matplotlib.axis.Tick 是我们最终的容器对象。Tick 包含刻度和网格线实例,以及上下刻度的标签实例。这些中的每一个都可以直接作为 Tick 的属性访问。
Tick 属性 |
描述 |
|---|---|
tick1line |
一个 |
tick2line |
一个 |
网格线 |
一个 |
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()