注意
转到末尾 下载完整的示例代码。
艺术家教程#
使用 Artist 对象在画布上渲染。
Matplotlib API 有三层。
the
matplotlib.backend_bases.FigureCanvas
是绘制图形的区域the
matplotlib.backend_bases.Renderer
是知道如何在FigureCanvas
上绘制的对象以及
matplotlib.artist.Artist
是知道如何使用渲染器在画布上绘制的对象。
The FigureCanvas
和 Renderer
处理与用户界面工具包(如 wxPython)或 PostScript® 等绘图语言进行通信的所有细节,而 Artist
处理所有高级结构,例如表示和布局图形、文本和线条。 典型的用户会将 95% 的时间花在与 Artists
上。
There are two types of Artists
: primitives and containers. The primitives
represent the standard graphical objects we want to paint onto our canvas:
Line2D
, Rectangle
,
Text
, AxesImage
, etc., and
the containers are places to put them (Axis
,
Axes
and Figure
). The
standard use is to create a Figure
instance, use
the Figure
to create one or more Axes
instances, and use the Axes
instance
helper methods to create the primitives. In the example below, we create a
Figure
instance using matplotlib.pyplot.figure()
, which is a
convenience method for instantiating Figure
instances and connecting them
with your user interface or drawing toolkit FigureCanvas
. As we will
discuss below, this is not necessary -- you can work directly with PostScript,
PDF Gtk+, or wxPython FigureCanvas
instances, instantiate your Figures
directly and connect them yourselves -- but since we are focusing here on the
Artist
API we'll let pyplot
handle some of those details
for us:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(2, 1, 1) # two rows, one column, first plot
The Axes
is probably the most important
class in the Matplotlib API, and the one you will be working with most
of the time. This is because the Axes
is the plotting area into
which most of the objects go, and the Axes
has many special helper
methods (plot()
,
text()
,
hist()
,
imshow()
) to create the most common
graphics primitives (Line2D
,
Text
,
Rectangle
,
AxesImage
, respectively). These helper methods
will take your data (e.g., numpy
arrays and strings) and create
primitive Artist
instances as needed (e.g., Line2D
), add them to
the relevant containers, and draw them when requested. If you want to create
an Axes
at an arbitrary location, simply use the
add_axes()
method which takes a list
of [left, bottom, width, height]
values in 0-1 relative figure
coordinates:
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
时,它会将信息传递给 Text
实例的 XAxis
。每个 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
(“Patch” 是从 MATLAB 继承的名称,是图上 2D 的颜色“补丁”,例如矩形、圆形和多边形)。每个 Matplotlib Artist
都有以下属性
属性 |
描述 |
---|---|
alpha |
透明度 - 0 到 1 之间的标量 |
animated |
用于促进动画绘制的布尔值 |
axes |
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 访问(是的,我们知道这会让 Pythonistas 感到恼火,我们计划通过属性或特性支持直接访问,但目前还没有实现)。例如,要将当前 alpha 值乘以 0.5
a = o.get_alpha()
o.set_alpha(0.5*a)
如果您想一次设置多个属性,也可以使用 set
方法,并使用关键字参数。例如
o.set(alpha=0.5, zorder=2)
如果您在 Python shell 中进行交互式操作,可以使用 matplotlib.artist.getp()
函数(在 pyplot 中简称为 getp()
)来方便地检查 Artist
属性,该函数会列出属性及其值。这同样适用于从 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 轴是“线性”还是“对数”。在本节中,我们将回顾各种容器对象存储要获取的 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>]
由于图形维护着“当前坐标轴”的概念(参见 Figure.gca
和 Figure.sca
)来支持 pylab/pyplot 状态机,您不应该直接从坐标轴列表中插入或删除坐标轴,而应该使用 add_subplot()
和 add_axes()
方法插入,并使用 Axes.remove
方法删除。但是,您可以自由地遍历坐标轴列表或索引到其中以获取您想要自定义的 Axes
实例。以下是一个将所有坐标轴网格打开的示例
该图形也有自己的 images
、lines
、patches
和 text
属性,您可以使用它们直接添加基本图形。这样做时,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()
以下是图形包含的 Artist 的摘要
图形属性 |
描述 |
---|---|
axes |
|
patch |
|
images |
|
legends |
图形 |
lines |
图形 |
patches |
Figure |
texts |
Figure |
Axes 容器#
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
中,并将其返回给您。
plot
返回一个线列表,因为您可以传入多个 x, y 对进行绘图,我们正在将长度为一的列表的第一个元素解包到 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
,它们负责绘制刻度和标签。它们作为实例变量 xaxis
和 yaxis
存储。 XAxis
和 YAxis
容器将在下面详细介绍,但请注意,Axes
包含许多辅助方法,这些方法将调用转发到 Axis
实例,因此您通常不需要直接使用它们,除非您想这样做。例如,您可以使用 Axes
辅助方法设置 XAxis
刻度标签的字体颜色
以下是 Axes
包含的 Artists 摘要
Axes 属性 |
描述 |
---|---|
artists |
一个 |
patch |
|
collections |
一个 |
images |
一个 |
lines |
一个 |
patches |
一个 |
texts |
一个 |
x 轴 |
一个 |
y 轴 |
一个 |
图例可以通过 get_legend
访问。
轴容器#
The matplotlib.axis.Axis
实例负责绘制刻度线、网格线、刻度标签和轴标签。您可以分别配置 y 轴的左侧和右侧刻度,以及 x 轴的上侧和下侧刻度。The 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
的一些有用访问器方法的摘要(这些方法有相应的设置器,例如 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()
刻度容器#
从 Figure
到 Axes
再到 Axis
最后到 Tick
,matplotlib.axis.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.089 秒)