艺术家教程#

使用 Artist 对象在画布上渲染。

Matplotlib API 共有三层。

  • matplotlib.backend_bases.FigureCanvas绘制图形的区域

  • matplotlib.backend_bases.Renderer知道如何在FigureCanvas

  • 并且matplotlib.artist.Artist是知道如何使用渲染器在画布上绘画的对象。

FigureCanvasRenderer处理与用户界面工具包(如wxPython)或绘图语言(如 PostScript®)对话的所有细节,并处理Artist所有高级构造,如表示和布置图形、文本和线条。典型用户将花费 95% 的时间使用Artists.

有两种类型Artists:原语和容器。原语代表我们想要在画布上绘制的标准图形对象: Line2DRectangleTextAxesImage等,而容器是放置它们的地方(AxisAxesFigure。标准用法是创建一个Figure实例,使用Figure创建一个或多个Axes或 多个Subplot实例,并使用Axes实例辅助方法创建基元。在下面的示例中,我们使用 来创建一个 Figure实例,这是一种用于实例化实例并将它们与您的用户界面或绘图工具包连接起来matplotlib.pyplot.figure()的便捷方法FigureFigureCanvas. 正如我们将在下面讨论的那样,这不是必需的——您可以直接使用 PostScript、PDF Gtk+ 或 wxPythonFigureCanvas实例,Figures 直接实例化您的实例并自己连接它们——但是由于我们在这里专注于 ArtistAPI,我们将让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())来创建最常见的图形基元(分别为Line2DTextRectangleAxesImage)。这些辅助方法将获取您的数据(例如,numpy数组和字符串)并Artist根据需要创建原始实例(例如,Line2D),将它们添加到相关容器中,并在请求时绘制它们。Subplot你们中的大多数Axes人可能熟悉Subplot实例。如果要Axes在任意位置创建一个,只需使用 在 0-1 相对图形坐标add_axes()中获取值列表的方法:[left, bottom, width, height]

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是上面调用Axes创建的实例 fig.add_subplot(记住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(并且保持状态为“on”,这是默认设置),则其他行将添加到列表中。您可以稍后通过调用其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,它会传递关于Text 实例的信息XAxis。每个Axes 实例都包含一个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('volts')
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实例来确定轴的颜色、透明度和其他属性。这些实例存储为成员变量Figure.patch,并且Axes.patch(“补丁”是名称继承自 MATLAB,是图形上的 2D 颜色“补丁”,例如矩形、圆形和多边形)。每个 MatplotlibArtist都具有以下属性

财产

描述

α

透明度 - 0-1 的标量

动画

用于促进动画绘制的布尔值

艺术家居住的斧头,可能没有

剪辑框

剪辑艺术家的边界框

夹上

是否启用剪辑

剪辑路径

艺术家被剪辑到的路径

包含

用于测试艺术家是否包含拾取点的拾取函数

数字

艺术家居住的人物实例,可能没有

标签

文本标签(例如,用于自动标记)

拣货员

一个控制对象拾取的python对象

转换

转型

可见的

是否应绘制艺术家的布尔值

佐德

决定绘制顺序的数字

光栅化

布尔值;将矢量转换为光栅图形(用于压缩和 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()函数(仅 getp()在 pyplot 中),它列出了属性及其值。这也适用于派生自的类Artist,例如FigureRectangle。以下是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 实例的字体, a 的宽度Line2D),尽管容器也有一些属性 - 例如,它 是一个容器,其中包含绘图中的许多基元,但是它还具有控制 xaxis 是“线性”还是“对数”等属性。在本节中,我们将回顾各种容器对象存储您想要获取的对象的位置。Axes ArtistxscaleArtists

图容器#

顶级容器Artistmatplotlib.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]: <AxesSubplot:>

In [160]: print(fig.axes)
[<AxesSubplot:>, <matplotlib.axes._axes.Axes object at 0x7f0768702be0>]

因为图中维护了“当前Axes”的概念(见 Figure.gcaand Figure.sca)来支持pylab/pyplot状态机,所以不应该直接从Axes列表中插入或者移除Axes,而是使用 add_subplot()and add_axes()方法插入, Axes.remove方法删除。但是,您可以自由地遍历 Axes 列表或对其进行索引以访问Axes您想要自定义的实例。这是一个打开所有轴网格的示例:

for ax in fig.axes:
    ax.grid(True)

该图窗还具有自己的images、和属性lines, 您可以使用它们直接添加基元。这样做时,默认坐标系将简单地以像素为单位(这通常不是您想要的)。如果您改为使用图形级别的方法来添加艺术家(例如,用于添加文本),那么默认坐标系将是“图形坐标”,其中 (0, 0) 是图形的左下角, (1, 1 ) 是图的右上角。patchestextFigureFigure.text

和所有Artist的s一样,你可以通过设置transform属性来控制这个坐标系。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()
艺术家

这是图中包含的艺术家的摘要

图属性

描述

实例列表Axes(包括子图)

修补

Rectangle背景_

图片

补丁列表FigureImage- 用于原始像素显示

传说

FigureLegend实例列表(不同于Axes.get_legend()

线条

FigureLine2D实例列表(很少使用,请参阅Axes.lines

补丁

FigurePatch的列表(很少使用,请参阅Axes.patches

文本

一个列表图Text实例

轴容器#

matplotlib.axes.Axes是 Matplotlib 世界的中心——它包含了图形中使用的绝大多数内容,其中包含Artists许多帮助方法来创建和添加这些 内容Artists,以及访问和自定义Artists其中包含的帮助方法。与 一样 Figure,它包含 a ,它是 笛卡尔坐标的 a 和极坐标的 a ;这个补丁决定了绘图区域的形状、背景和边框:Patch patchRectangleCircle

ax = fig.add_subplot()
rect = ax.patch  # a Rectangle instance
rect.set_facecolor('green')

当您调用绘图方法时,例如,canonical 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 对来绘图,并且我们将长度为一个列表的第一个元素解包到行变量中。该行已添加到 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.linesorAxes.patches 列表中,因为在Axes创建和添加对象时需要做一些事情:

  • 它设置;的figureandaxes属性Artist

  • 它设置默认Axes转换(除非已经设置);

  • 它检查包含在 中的Artist数据以更新控制自动缩放的数据结构,以便可以调整视图限制以包含绘制的数据。

不过,您可以自己创建对象并将它们直接添加到 Axesusing 辅助方法中,例如add_lineadd_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它们创建的类型以及它们的存储位置

轴辅助方法

艺术家

容器

annotate- 文本注释

Annotation

斧头文本

bar- 条形图

Rectangle

斧头补丁

errorbar- 误差线图

Line2DRectangle

ax.lines 和 ax.patches

fill- 共享区域

Polygon

斧头补丁

hist- 直方图

Rectangle

斧头补丁

imshow- 图像数据

AxesImage

斧头图像

legend- 轴传奇

Legend

ax.get_legend()

plot- xy地块

Line2D

轴线

scatter- 散点图

PolyCollection

ax.collections

text- 文本

Text

斧头文本

除了所有这些之外ArtistsAxes还包含两个重要Artist的容器:XAxisYAxis,它们处理刻度和标签的绘制。这些存储为实例变量 xaxisyaxis. XAxisYAxis 容器将在下面详细介绍,但请注意,其中包含Axes许多将调用转发到 Axis实例的辅助方法,因此您通常不需要直接使用它们,除非您愿意。例如,您可以XAxis使用Axes辅助方法设置刻度标签的字体颜色:

ax.tick_params(axis='x', labelcolor='orange')

以下是Axes包含的艺术家的摘要

轴属性

描述

艺术家

一个实例ArtistList_Artist

修补

RectangleAxes 背景的实例

收藏品

一个实例ArtistList_Collection

图片

一个ArtistList_AxesImage

线条

一个实例ArtistList_Line2D

补丁

一个实例ArtistList_Patch

文本

一个实例ArtistList_Text

x轴

一个matplotlib.axis.XAxis实例

y轴

一个matplotlib.axis.YAxis实例

图例可以通过get_legend,

轴容器#

这些matplotlib.axis.Axis实例处理刻度线、网格线、刻度标签和轴标签的绘制。您可以为 y 轴分别配置左右刻度,为 x 轴分别配置上下刻度。Axis 还存储用于自动缩放、平移和缩放的数据和视图间隔,以及控制刻度放置位置以及如何将它们表示为字符串的和实例LocatorFormatter

每个Axis对象都包含一个label属性(这是pyplot在调用xlabeland 中修改的内容ylabel)以及主要和次要刻度的列表。刻度是 axis.XTickaxis.YTick实例,其中包含渲染刻度和刻度标签的实际行和文本基元。因为刻度是根据需要动态创建的(例如,在平移和缩放时),您应该通过它们的访问器方法访问主要和次要刻度的 axis.Axis.get_major_ticks列表axis.Axis.get_minor_ticks。尽管刻度包含所有基元并将在下面进行介绍,但Axis 实例具有返回刻度线、刻度标签、刻度位置等的访问器方法:

艺术家
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')]

请注意,刻度线的数量是标签的两倍,因为默认情况下,顶部和底部都有刻度线,但只有 xaxis 下方的刻度线;但是,这可以定制。

<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()。)

轴访问器方法

描述

get_scale

轴的比例,例如“对数”或“线性”

get_view_interval

轴视图限制的间隔实例

get_data_interval

Axis 数据限制的区间实例

get_gridlines

轴的网格线列表

get_label

Axis 标签 - 一个Text实例

get_offset_text

轴偏移文本 - 一个Text实例

get_ticklabels

实例列表Text- 关键字 minor=True|False

get_ticklines

实例列表Line2D- 关键字 minor=True|False

get_ticklocs

Tick 位置列表 - 关键字 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 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()
艺术家

勾选容器#

The是我们从到 到 到 的 下降matplotlib.axis.Tick过程中的最后一个容器对象。包含刻度和网格线实例,以及上下刻度的标签实例。这些中的每一个都可以作为.FigureAxesAxisTickTickTick

勾选属性

描述

滴答1线

一个Line2D实例

tick2line

一个Line2D实例

网格线

一个Line2D实例

标签1

一个Text实例

标签2

一个Text实例

这是一个示例,它使用美元符号设置右侧刻度的格式化程序,并在 y 轴的右侧将它们着色为绿色。

import numpy as np
import matplotlib.pyplot as plt

# 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.067秒)

由 Sphinx-Gallery 生成的画廊