注意
转到末尾下载完整的示例代码。
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 秒)