使用Artist对象来渲染画布。
matplotlib API一共有三个层次:
matplotlib.backend_bases.FigureCanvas
是绘制图形的区域;matplotlib.backend_bases.Renderer
是知道如何在FigureCanvas
上绘制的对象;matplotlib.artist.Artist
是知道如何使用渲染器在画布上绘图的对象。FigureCanvas
和Renderer
处理与用户界面工具包(如wxPython)或绘图语言(如PostScript)通信的所有细节。而Artist
处理所有高级构造,如表示和布局图形、文本和线条 。用户通常要花费95%的时间使用Artists
。
有两种类型的Artist
:基元和容器。基元表示我们要在画布上绘制的标准图形对象:Line2D
、Rectangle
、Text
、AxesImage
等;容器是放置它们的地方(Axis
、Axes
、Figure
)。标准用法是创建一个Figure实例,并使用Figure
来创建一个或多个Axes
实例,并使用Axes
实例帮助程序方法创建基元。在下面的示例中,我们使用matplotlib.pyplot.figure()
创建一个Figure
实例,这是一种实例化Figure
实例并将它们与你的用户界面或绘图工具包FigureCanvas
连接起来的便捷方法。正如我们将在下面讨论的,这不是必需的——你可以直接使用PostScript
,PDFGtk+
,或者wxPython
FigureCanvas
实例,直接实例化你的Figure
并自己连接它们。但是由于我们在这里专注于Artist API
,我们将让pyplot
为我们处理其中一些细节:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(2, 1, 1) # 子图布局为两行,一列,先指定第一张图
Axes
可能是matplotlib API
中最重要的类,也是你大部分时间都会使用的类。这是因为axes
是大多数对象进入的绘图区域,并且axes
有许多特殊的辅助方法(plot()
,text()
,hist()
,imshow()
)来创建最常见的图形基元(分别为Line2D
,Text
, Rectangle
,AxesImage
)。这些帮助程序方法将获取你的数据(例如,numpy
数组和字符串)并根据需要创建基元Artist
实例(例如Line2D
),将它们添加到相关窗口中,并在请求时绘制它们。如果要在任意位置创建axes
,只需要使用add_axes()
方法,该方法在0-1个相对图形坐标中获取[左、底、宽、高]值列表:
fig2 = plt.figure()
ax2 = fig2.add_axes([0.15, 0.1, 0.7, 0.3])
如图,左侧位置在0.15处,底侧位置在0.1处,宽度为0.7,则右侧位置到0.85处,刚好控制左右边距对称,高度到0.4处。
继续我们的例子:
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,并且包含该行返回的同一行 =ax.plot...
调用:
ax.lines[0]
Out[101]: <matplotlib.lines.Line2D at 0x19a95710>
line
Out[102]: <matplotlib.lines.Line2D at 0x19a95710>
如果你随后调用ax.plot
(并且保持状态为默认值 “on”),则其他线将会被添加到列表中。你可以稍后通过调用其remove
方法来删除一条线:
line = ax.lines[0]
line.remove()
Axes
还具有用于配置和修饰x轴和y轴刻度、刻度标签和轴标签的帮助器方法:
xtext = ax.set_xlabel('my xdata') # 返回一个文本实例
ytext = ax.set_ylabel('my ydata')
调用ax.set_xlabel
时,它会传递有关XAxis的文本实例上的信息。每个轴实例都包含一个XAxis和一个YAxis实例,它们处理刻度、刻度标签和轴标签的布局和绘制。
尝试绘制以下的图:
import numpy as np
import matplotlib.pyplot as plt
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)
# 控制复现时的随机种子
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
表示,每个元素都有一个广泛的属性列表来配置其外观。图形本身包含一个与图形大小完全相同的矩形,可用于设置图形的背景颜色和透明度。同样,每个axes
边界框(典型的matplotlib
图中带有黑色边缘的标准白框)都有一个矩形实例,用于确定axes
对象的颜色、透明度和其他属性。这些实例存储为成员变量Figure.patch
和Axes.patch
("Patch"是从MATLAB
中继承的名称,是图形上颜色的2D“补丁”,例如矩形、圆形和多边形)。每个matplotlib
的artist
都有以下属性:
属性 | 描述 |
---|---|
alpha | 透明度——一个介于0-1之间的标量 |
animated | 一个布尔值,用来配置动画绘制 |
axes | Artist存在的位置,可能没有 |
clip_box | 包围着Artist对象的边框 |
clip_on | 是否启用裁剪 |
clip_path | artist被剪辑到的路径 |
contains | 用于测试artist是否包含拾取点的拾取函数 |
figure | artist所在的figure实例,可能没有 |
label | 文本标签(例如:自动标签) |
picker | 一个控制对象拾取的python对象 |
transform | 转型 |
visible | 一个控制artist是否可见的布尔值 |
zorder | 控制绘制顺序的数字 |
rasterized | 布尔值,将矢量转换为光栅图形(用于压缩和EPS)透明度 |
每个属性都可以使用老式的setter
或getter
访问(是的,我们知道这激怒了Pythonistas
,我们计划支持通过属性或特征直接访问在,但尚未完成)。例如,要将当前的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
。下面是上面提到的图形矩形属性:
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
以获取给定对象的属性列表。
现在我们知道了如何检查和设置要配置的给定对象的属性,我们需要知道如何获取该对象。如引言中所述,有两种对象:基元和容器。基元通常是你要配置的内容(文本实例的字体,line2D
的宽度),尽管容器也具有一些属性——例如,Axes Artist
是一个容器,其中包含绘图中的许多基元,但它也具有像xcale
这样的属性来控制xaxis
是“线性”还是“对数”。这本节中,我们将回顾各种容器对象存储你想要获取的Artist
的位置。
最顶层的容器Artist
是matplotlib.figure.Figure
,它包含图中的所有内容。该图的背景是一个存储在Figure.patch
中的矩形。当你向图形添加子图(add_subplot())和axes(add_axes())时,这些将附加到Figure.axes
。这些也由创建它们的方法返回:
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_axes([0.1, 0.1, 0.7, 0.3])
ax1
Out[159]: <Axes:>
print(fig.axes)
[<Axes:>, <matplotlib.axes._axes.Axes object at 0x7f0768702be0>]
由于该图保留了“当前Axes”的概念(请参阅Figure.gca
和Figure.sca
)以支持pylab/pyplot
状态机,因此不应直接从Axes列表中插入或删除轴,而应使用add_subplot()
和add_axes()
方法插入,并使用Axes.remove
方法删除。但是,你可以自由地迭代axes
列表或索引 到其中以访问要自定义的Axes
实例。下面是一个打开所有Axes
网格的示例:
for ax in fig.axes:
ax.grid(True)
该图还具有自己的图像、线条、图块和文本属性,你可以使用它们直接添加基元。执行此操作时,图形的默认坐标系将仅以像素为单位(这通常不是你想要的)。如果你改用Figure
级该应地来添加Artist
(例如,使用Figure.text
添加文本),则默认坐标系将是“图形坐标”,其中(0,0)是图形的左下角,(1,1)是图形的右上角。
与所有Artist
一样,你可以通过设置transform
属性来控制此坐标系。你可以通过将Aritst
转换设置为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
包含的Artist
的摘要:
Figure属性 | 描述 |
---|---|
axes | Axes 实例的列表 |
patch | Rectangle 矩形背景 |
images | FigureImage 补丁的列表——原始像素显示有用 |
legends | 图像图例Legend 实例的列表(和Axes.get_legend() 不同) |
lines | 图像line2D 实例中的列表(极少使用,见Axes.lines ) |
patches | 图像Patch 列表(极少使用,见Axes.patches ) |
texts | 图像Text 实例列表 |
matplotlib.axes.Axes
是Matplotlib
宇宙的中心——它包含图中使用的绝大多数Artist
,有许多帮助程序方法来创建和添加这些Artist
到自身,以及访问和自定义它所包含的Artist
的辅助方法。像Figure
一样,它包含一个补丁patch
,它是笛卡尔坐标的矩形和极坐标的圆;此图块确定绘图区域的形状、背景和边框:
ax = fig.add_subplot()
rect = ax.patch # a Rectangle instance
rect.set_facecolor('green')
当你调用一个绘图方法(例如,标准绘图并传入数组或值列表)时,该方法创建一个matplotlib.lines.Line2D
实例,使用作为关键字参数传递的所有line2D
属性更新该直线,将该直线添加到Axes
中,然后将其返回给你:
x, y = np.random.rand(2, 100)
line, = ax.plot(x, y, '-', color='blue', linewidth=2)
plot
返回一个直线列表,因为你可以传入多个x,y对来绘制,我们将长度列表的第一个元素解压缩到line变量中。该直线已经添加到Axes.lines
列表中:
print(ax.lines)
[<matplotlib.lines.Line2D at 0xd378b0c>]
类似地,创建补丁patch
的方法,如bar()
创建一个矩形列表,会将补丁添加到Axes.patches
列表中:
n, bins, rectangles = ax.hist(np.random.randn(1000), 50)
rectangles
<BarContainer object of 50 artists>
print(len(ax.patches))
50
你不应该将对象直接添加到Axes.lines
或Axes.patches
列表中,因为Axes
在创建和添加对象时还需要执行一些操作:
Artist
的Figure
和Axes
属性;Axes
变换(除非已经设置了一个);Artist
中包含的数据以更新控制自动缩放的数据结构,以便可以调整视图限制以包含打印数据。不过,你可以自己创建对象,并使用如add_line
和add_patch
等方法将它们直接添加到Axes
中。这是一个带注释的交互式会话,它说明了发生了的一些事情:
fig, ax = plt.subplots()
# 创建一个矩形实例
rect = matplotlib.patches.Rectangle((1, 1), width=5, height=12)
# 默认时axes实例为None
print(rect.axes)
None
# transformation实例设置成"identity transform"
print(rect.get_data_transform())
IdentityTransform()
# 接着我们将矩形添加到Axes上去
ax.add_patch(rect)
# 注意ax.add_patch方法已经设置了axes实例
print(rect.axes)
Axes(0.125,0.1;0.775x0.8)
# 并且transformation也已经设置好了
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.]])))))))
# 默认的axes转换是 ax.transData
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.]])))))))
# 注意Axes的x轴极限没有被改变
print(ax.get_xlim())
(0.0, 1.0)
# 但是数据限制已经更新为包含矩形
print(ax.dataLim.bounds)
(1.0, 1.0, 5.0, 12.0)
# 我们可以手动调用自动缩放机制
ax.autoscale_view()
# 现在xlim已经更新为包含矩形,加上边距
print(ax.get_xlim())
(0.75, 6.25)
# 我们必须手动强制绘制图形
fig.canvas.draw()
有许多Axes
帮助程序方法可用于创建基元Artists
并将它们添加到各自的容器中去。下表总结了它们中的一小部分样本、它们创建的Artist
以及存储它们的位置:
Axes帮助程序方法 | Artist | 容器 |
---|---|---|
annotate -文本注释 |
Annotation |
ax.texts |
bar -柱形图 |
Rectangle |
ax.patches |
errorbar -误差柱形图 |
Line2D 及Rectangle |
ax.lines 和 ax.patches |
fill -填充区域 |
Polygon |
ax.patches |
hist -直方图 |
Rectangle |
ax.patches |
imshow -图像数据 |
AxesImage |
ax.images |
legend -图例 |
Legend |
ax.get_legend() |
plot -xy折线图 |
Line2D |
ax.lines |
scatter -散点图 |
PolyCollection |
ax.collections |
text -文本 |
Text |
ax.texts |
除了所有这些Artist
之外,Axes
还包含有两个重要的Artist
容器:XAxis
及YAxis
,它们控制刻度和标签的绘制。它们存储为实例变量xaxis
和yaxis
。下面将详细介绍XAxis
和YAxis
容器,但请注意,Axes
包含许多将调用转发到Axis
实例的帮助程序方法,因此除非你愿意,否则通常不需要直接使用它们。例如,你可以使用Axes
帮助程序方法设置XAxis
刻度标签的字体颜色:
ax.tick_params(axis='x', labelcolor='orange')
这就把字体的颜色设置成了橙色。
以下是一些Axes
包含的Artist
的总结:
Axes属性 | 描述 |
---|---|
artists | 一个ArtistList 或Artist 实例 |
patch | Axes背景的Rectangle 实例 |
collections | 一个ArtistList 或Collection 实例 |
images | 一个AxesImage 中的ArtistList |
patches | 一个ArtistList 或Patch 实例 |
texts | 一个ArtistList 或Text 实例 |
xaxis | 一个matplotlib.axis.XAxis 实例 |
yaxis | 一个matplotlib.axis.YAxis 实例 |
图例则可以通过get_legend
进行访问。
matplotlib.axis.Axis
实例控制刻度线、网格线、刻度标签和轴标签的线控制。你可以分别为y轴配置左刻度和右刻度,为x轴分别配置上刻度及下刻度。轴还存储用于自动缩放、平移和缩放的数据和视图间隔,以及控制刻度放置位置以及如何将它们表示为字符串的定位器和格式化程序实例。
每个Axis对象都包含一个标签属性(这是pyplot
在调用xlabel
及ylabel
时修改的属性)以及主要和次要刻度的列表。刻度是axis.XTick
和axis.YTick
实例(取决于是x轴的刻度还是y轴的刻度),其中包含呈现刻度标签的实际行和文本基元。由于刻度是根据需要动态创建的(例如,在平移和缩放时),因此你应该通过其访问器方法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')]
请注意,刻度线的数量是标签的两倍,因为在默认情况下,顶部和底部都有刻度线,只有轴下方的刻度有标签,但这也可以自己定义。
axis.get_ticklines()
输出为:
<a list of 12 Line2D ticklines objects>
以下是Axis的一些有用的访问器方法的摘要(这些方法在有用的地方有相应的setter
,例如set_major_formatter()
)。
Axis访问器方法 | 描述 |
---|---|
get_scale |
轴的比例,如’log’和’linear’ |
get_view_interval |
轴视图上下限的间隔实例 |
get_data_interval |
轴数据上下限的间隔实例 |
get_gridlines |
轴的轴线列表 |
get_label |
轴标签——一个Text 实例 |
get_offset_text |
轴补偿实例——一个Text 实例 |
get_ticklabels |
一个Line2D 实例列表-关键词minor=True|False |
get_ticklocs |
刻度位置的列表-关键词minor=True|False |
get_major_locator |
主刻度的ticker.Locator 实例 |
get_major_formatter |
主刻度的ticker.formatter 实例 |
get_minor_locator |
次刻度的ticker.Locator 实例 |
get_minor_formatter |
次刻度的ticker.formatter 实例 |
get_major_ticks |
主刻度的Tick 实例列表 |
get_minor_ticks |
次刻度的Tick 实例列表 |
grid |
打开或关闭主次刻度线的开关 |
以下是一个例子,因为实在不好看,所以不推荐这样做,它自定义了Axes和Tick的属性:
# plt.figure 创建了一个 matplotlib.figure.Figure 实例
fig = plt.figure()
rect = fig.patch # 一个矩形实例
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.set_color('red')
label.set_rotation(45)
label.set_fontsize(16)
for line in ax1.yaxis.get_ticklines():
# 直线是一个 Line2D 实例
line.set_color('green')
line.set_markersize(25)
line.set_markeredgewidth(3)
plt.show()
matplotlib.axis.Tick
是我们从Figure到Axes再到Axis再到Tick下降过程中的最后一个容器对象。刻度包含刻度和网格线实例,以及上刻度和下刻度的标签实例。这些中的每一个都可以作为Tick的属性直接进行访问。
Tick属性 | 描述 |
---|---|
tick1line | 一个Line2D 实例 |
tick2line | 一个Line2D 实例 |
gridline | 一个Line2D 实例 |
label1 | 一个Text 实例 |
label2 | 一个Text 实例 |
下面一个示例,它用美元符号为右侧刻度设置格式,并在yaxis的右侧将它们着色为绿色。
import numpy as np
import matplotlib.pyplot as plt
# 固定随机数种子
np.random.seed(19680801)
fig, ax = plt.subplots()
ax.plot(100*np.random.rand(20))
# 使用自动的格式设置
ax.yaxis.set_major_formatter('${x:1.2f}')
ax.yaxis.set_tick_params(which='major', labelcolor='green',
labelleft=False, labelright=True)
plt.show()