返回介绍

matplotlib-绘制精美的图表

发布于 2025-02-25 22:46:17 字数 23374 浏览 0 评论 0 收藏 0

matplotlib 是 python 最著名的绘图库,它提供了一整套和 matlab 相似的命令 API,十分适合交互式地进行制图。而且也可以方便地将它作为绘图控件,嵌入 GUI 应用程序中。

它的文档相当完备,并且 Gallery 页面 中有上百幅缩略图,打开之后都有源程序。因此如果你需要绘制某种类型的图,只需要在这个页面中浏览/复制/粘贴一下,基本上都能搞定。

本章节作为 matplotlib 的入门介绍,将较为深入地挖掘几个例子,从中理解和学习 matplotlib 绘图的一些基本概念。

快速绘图

matplotlib 的 pyplot 子库提供了和 matlab 类似的绘图 API,方便用户快速绘制 2D 图表。让我们先来看一个简单的例子:

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 1000)
y = np.sin(x)
z = np.cos(x**2)

plt.figure(figsize=(8,4))
plt.plot(x,y,label="$sin(x)$",color="red",linewidth=2)
plt.plot(x,z,"b--",label="$cos(x^2)$")
plt.xlabel("Time(s)")
plt.ylabel("Volt")
plt.title("PyPlot First Example")
plt.ylim(-1.2,1.2)
plt.legend()
plt.show()

调用 pyplot 库快速将数据绘制成曲线图

matplotlib 中的快速绘图的函数库可以通过如下语句载入:

import matplotlib.pyplot as plt

pylab 模块

matplotlib 还提供了名为 pylab 的模块,其中包括了许多 numpy 和 pyplot 中常用的函数,方便用户快速进行计算和绘图,可以用于 IPython 中的快速交互式使用。

接下来调用 figure 创建一个绘图对象,并且使它成为当前的绘图对象。

plt.figure(figsize=(8,4))

也可以不创建绘图对象直接调用接下来的 plot 函数直接绘图,matplotlib 会为我们自动创建一个绘图对象。如果需要同时绘制多幅图表的话,可以是给 figure 传递一个整数参数指定图标的序号,如果所指定序号的绘图对象已经存在的话,将不创建新的对象,而只是让它成为当前绘图对象。

通过 figsize 参数可以指定绘图对象的宽度和高度,单位为英寸;dpi 参数指定绘图对象的分辨率,即每英寸多少个像素,缺省值为 80。因此本例中所创建的图表窗口的宽度为 8*80 = 640 像素。

但是用工具栏中的保存按钮保存下来的 png 图像的大小是 800*400 像素。这是因为保存图表用的函数 savefig 使用不同的 DPI 配置,savefig 函数也有一个 dpi 参数,如果不设置的话,将使用 matplotlib 配置文件中的配置,此配置可以通过如下语句进行查看,关于配置文件将在后面的章节进行介绍:

>>> import matplotlib
>>> matplotlib.rcParams["savefig.dpi"]
100

下面的两行程序通过调用 plot 函数在当前的绘图对象中进行绘图:

plt.plot(x,y,label="$sin(x)$",color="red",linewidth=2)
plt.plot(x,z,"b--",label="$cos(x^2)$")

plot 函数的调用方式很灵活,第一句将 x,y 数组传递给 plot 之后,用关键字参数指定各种属性:

  • label : 给所绘制的曲线一个名字,此名字在图示(legend) 中显示。只要在字符串前后添加"$"符号,matplotlib 就会使用其内嵌的 latex 引擎绘制的数学公式。
  • color : 指定曲线的颜色
  • linewidth : 指定曲线的宽度

第二句直接通过第三个参数"b--"指定曲线的颜色和线型,这个参数称为格式化参数,它能够通过一些易记的符号快速指定曲线的样式。其中 b 表示蓝色,"--"表示线型为虚线。在 IPython 中输入 "plt.plot?" 可以查看格式化字符串的详细配置。

接下来通过一系列函数设置绘图对象的各个属性:

plt.xlabel("Time(s)")
plt.ylabel("Volt")
plt.title("PyPlot First Example")
plt.ylim(-1.2,1.2)
plt.legend()
  • xlabel : 设置 X 轴的文字
  • ylabel : 设置 Y 轴的文字
  • title : 设置图表的标题
  • ylim : 设置 Y 轴的范围
  • legend : 显示图示

最后调用 plt.show() 显示出我们创建的所有绘图对象。

配置属性

matplotlib 所绘制的图的每个组成部分都对应有一个对象,我们可以通过调用这些对象的属性设置方法 set_*或者 pyplot 的属性设置函数 setp 设置其属性值。例如 plot 函数返回一个 matplotlib.lines.Line2D 对象的列表,下面的例子显示如何设置 Line2D 对象的属性:

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> x = np.arange(0, 5, 0.1)
>>> line, = plt.plot(x, x*x) # plot 返回一个列表,通过 line,获取其第一个元素
>>> # 调用 Line2D 对象的 set_*方法设置属性值
>>> line.set_antialiased(False)
>>> # 同时绘制 sin 和 cos 两条曲线,lines 是一个有两个 Line2D 对象的列表
>>> lines = plt.plot(x, np.sin(x), x, np.cos(x)) #
>>> # 调用 setp 函数同时配置多个 Line2D 对象的多个属性值
>>> plt.setp(lines, color="r", linewidth=2.0)

这段例子中,通过调用 Line2D 对象 line 的 set_antialiased 方法,关闭对象的反锯齿效果。或者通过调用 plt.setp 函数配置多个 Line2D 对象的颜色和线宽属性。

同样我们可以通过调用 Line2D 对象的 get_*方法,或者 plt.getp 函数获取对象的属性值:

>>> line.get_linewidth()
1.0
>>> plt.getp(lines[0], "color") # 返回 color 属性
'r'
>>> plt.getp(lines[1]) # 输出全部属性
alpha = 1.0
animated = False
antialiased or aa = True
axes = Axes(0.125,0.1;0.775x0.8)
... ...

注意 getp 函数只能对一个对象进行操作,它有两种用法:

  • 指定属性名:返回对象的指定属性的值
  • 不指定属性名:打印出对象的所有属性和其值

matplotlib 的整个图表为一个 Figure 对象,此对象在调用 plt.figure 函数时返回,我们也可以通过 plt.gcf 函数获取当前的绘图对象:

>>> f = plt.gcf()
>>> plt.getp(f)
alpha = 1.0
animated = False
...

Figure 对象有一个 axes 属性,其值为 AxesSubplot 对象的列表,每个 AxesSubplot 对象代表图表中的一个子图,前面所绘制的图表只包含一个子图,当前子图也可以通过 plt.gca 获得:

>>> plt.getp(f, "axes")
[<matplotlib.axes.AxesSubplot object at 0x05CDD170>]
>>> plt.gca()
<matplotlib.axes.AxesSubplot object at 0x05CDD170>

用 plt.getp 可以发现 AxesSubplot 对象有很多属性,例如它的 lines 属性为此子图所包括的 Line2D 对象列表:

>>> alllines = plt.getp(plt.gca(), "lines")
>>> alllines
<a list of 3 Line2D objects>
>>> alllines[0] == line # 其中的第一条曲线就是最开始绘制的那条曲线
True

通过这种方法我们可以很容易地查看对象的属性和它们之间的包含关系,找到需要配置的属性。

绘制多轴图

一个绘图对象(figure) 可以包含多个轴(axis),在 Matplotlib 中用轴表示一个绘图区域,可以将其理解为子图。上面的第一个例子中,绘图对象只包括一个轴,因此只显示了一个轴(子图)。我们可以使用 subplot 函数快速绘制有多个轴的图表。subplot 函数的调用形式如下:

subplot(numRows, numCols, plotNum)

subplot 将整个绘图区域等分为 numRows 行 * numCols 列个子区域,然后按照从左到右,从上到下的顺序对每个子区域进行编号,左上的子区域的编号为 1。如果 numRows,numCols 和 plotNum 这三个数都小于 10 的话,可以把它们缩写为一个整数,例如 subplot(323) 和 subplot(3,2,3) 是相同的。subplot 在 plotNum 指定的区域中创建一个轴对象。如果新创建的轴和之前创建的轴重叠的话,之前的轴将被删除。

下面的程序创建 3 行 2 列共 6 个轴,通过 axisbg 参数给每个轴设置不同的背景颜色。

for idx, color in enumerate("rgbyck"):
  plt.subplot(320+idx+1, axisbg=color)
plt.show()

用 subplot 函数将 Figure 分为六个子图区域

如果希望某个轴占据整个行或者列的话,可以如下调用 subplot:

plt.subplot(221) # 第一行的左图
plt.subplot(222) # 第一行的右图
plt.subplot(212) # 第二整行
plt.show()

将 Figure 分为三个子图区域

当绘图对象中有多个轴的时候,可以通过工具栏中的 Configure Subplots 按钮,交互式地调节轴之间的间距和轴与边框之间的距离。如果希望在程序中调节的话,可以调用 subplots_adjust 函数,它有 left, right, bottom, top, wspace, hspace 等几个关键字参数,这些参数的值都是 0 到 1 之间的小数,它们是以绘图区域的宽高为 1 进行正规化之后的坐标或者长度。

配置文件

一幅图有许多需要配置的属性,例如颜色、字体、线型等等。我们在绘图时,并没有一一对这些属性进行配置,许多都直接采用了 Matplotlib 的缺省配置。Matplotlib 将缺省配置保存在一个文件中,通过更改这个文件,我们可以修改这些属性的缺省值。

Matplotlib 使用配置文件 matplotlibrc 时的搜索顺序如下:

  • 当前路径 : 程序的当前路径
  • 用户配置路径 : 通常为 HOME/.matplotlib/,可以通过环境变量 MATPLOTLIBRC 修改
  • 系统配置路径 : 保存在 matplotlib 的安装目录下的 mpl-data 下

通过下面的语句可以获取用户配置路径:

>>> import matplotlib
>>> matplotlib.get_configdir()
'C:\\Documents and Settings\\zhang\\.matplotlib'

通过下面的语句可以获得目前使用的配置文件的路径:

>>> import matplotlib
>>> matplotlib.matplotlib_fname()
'C:\\Python26\\lib\\site-packages\\matplotlib\\mpl-data\\matplotlibrc'

由于在当前路径和用户配置路径中都没有找到位置文件,因此最后使用的是系统配置路径下的配置文件。如果你将 matplotlibrc 复制一份到脚本的当前目录下:

>>> import os
>>> os.getcwd()
'C:\\zhang\\doc'

复制配置文件之后再运行:

>>> matplotlib.matplotlib_fname()
'C:\\zhang\\doc\\matplotlibrc'

如果你用文本编辑器打开此配置文件的话,你会发现它实际上是定义了一个字典。为了对众多的配置进行区分,关键字可以用点分开。

配置文件的读入可以使用 rc_params 函数,它返回一个配置字典:

>>> matplotlib.rc_params()
{'agg.path.chunksize': 0,
 'axes.axisbelow': False,
 'axes.edgecolor': 'k',
 'axes.facecolor': 'w',
 ... ...

在 matplotlib 模块载入的时候会调用 rc_params,并把得到的配置字典保存到 rcParams 变量中:

>>> matplotlib.rcParams
{'agg.path.chunksize': 0,
'axes.axisbelow': False,
... ...

matplotlib 将使用 rcParams 中的配置进行绘图。用户可以直接修改此字典中的配置,所做的改变会反映到此后所绘制的图中。例如下面的脚本所绘制的线将带有圆形的点标识符:

>>> matplotlib.rcParams["lines.marker"] = "o"
>>> import pylab
>>> pylab.plot([1,2,3])
>>> pylab.show()

为了方便配置,可以使用 rc 函数,下面的例子同时配置点标识符、线宽和颜色:

>>> matplotlib.rc("lines", marker="x", linewidth=2, color="red")

如果希望恢复到缺省的配置(matplotlib 载入时从配置文件读入的配置) 的话,可以调用 rcdefaults 函数。

>>> matplotlib.rcdefaults()

如果手工修改了配置文件,希望重新从配置文件载入最新的配置的话,可以调用:

>>> matplotlib.rcParams.update( matplotlib.rc_params() )

Artist 对象

matplotlib API 包含有三层:

  • backend_bases.FigureCanvas : 图表的绘制领域
  • backend_bases.Renderer : 知道如何在 FigureCanvas 上如何绘图
  • artist.Artist : 知道如何使用 Renderer 在 FigureCanvas 上绘图

FigureCanvas 和 Renderer 需要处理底层的绘图操作,例如使用 wxPython 在界面上绘图,或者使用 PostScript 绘制 PDF。Artist 则处理所有的高层结构,例如处理图表、文字和曲线等的绘制和布局。通常我们只和 Artist 打交道,而不需要关心底层的绘制细节。

Artists 分为简单类型和容器类型两种。简单类型的 Artists 为标准的绘图元件,例如 Line2D、 Rectangle、 Text、AxesImage 等等。而容器类型则可以包含许多简单类型的 Artists,使它们组织成一个整体,例如 Axis、 Axes、Figure 等。

直接使用 Artists 创建图表的标准流程如下:

  • 创建 Figure 对象
  • 用 Figure 对象创建一个或者多个 Axes 或者 Subplot 对象
  • 调用 Axies 等对象的方法创建各种简单类型的 Artists

下面首先调用 pyplot.figure 辅助函数创建 Figure 对象,然后调用 Figure 对象的 add_axes 方法在其中创建一个 Axes 对象,add_axes 的参数是一个形如[left, bottom, width, height]的列表,这些数值分别指定所创建的 Axes 对象相对于 fig 的位置和大小,取值范围都在 0 到 1 之间:

>>> import matplotlib.pyplot as plt
>>> fig = plt.figure()
>>> ax = fig.add_axes([0.15, 0.1, 0.7, 0.3])

然后我们调用 ax 的 plot 方法绘图,创建一条曲线,并且返回此曲线对象(Line2D)。

>>> line, = ax.plot([1,2,3],[1,2,1])
>>> ax.lines
[<matplotlib.lines.Line2D object at 0x0637A3D0>]
>>> line
<matplotlib.lines.Line2D object at 0x0637A3D0>

ax.lines 是一个为包含 ax 的所有曲线的列表,后续的 ax.plot 调用会往此列表中添加新的曲线。如果想删除某条曲线的话,直接从此列表中删除即可。

Axes 对象还包括许多其它的 Artists 对象,例如我们可以通过调用 set_xlabel 设置其 X 轴上的标题:

>>> ax.set_xlabel("time")

如果我们查看 set_xlabel 的源代码的话,会发现它是通过调用下面的语句实现的:

self.xaxis.set_label_text(xlabel)

如果我们一直跟踪下去,会发现 Axes 的 xaxis 属性是一个 XAxis 对象:

>>> ax.xaxis
<matplotlib.axis.XAxis object at 0x06343230>

XAxis 的 label 属性是一个 Text 对象:

>>> ax.xaxis.label
<matplotlib.text.Text object at 0x06343290>

而 Text 对象的_text 属性为我们设置的值:

>>> ax.xaxis.label._text
'time'

这些对象都是 Artists,因此也可以调用它们的属性获取函数来获得相应的属性:

>>> ax.xaxis.label.get_text()
'time'

Artist 的属性

图表中的每个元素都用一个 matplotlib 的 Artist 对象表示,而每个 Artist 对象都有一大堆属性控制其显示效果。例如 Figure 对象和 Axes 对象都有 patch 属性作为其背景,它的值是一个 Rectangle 对象。通过设置此它的一些属性可以修改 Figrue 图表的背景颜色或者透明度等属性,下面的例子将图表的背景颜色设置为绿色:

>>> fig = plt.figure()
>>> fig.show()
>>> fig.patch.set_color("g")
>>> fig.canvas.draw()

patch 的 color 属性通过 set_color 函数进行设置,属性修改之后并不会立即反映到图表的显示上,还需要调用 fig.canvas.draw() 函数才能够更新显示。

下面是 Artist 对象都具有的一些属性:

  • alpha : 透明度,值在 0 到 1 之间,0 为完全透明,1 为完全不透明
  • animated : 布尔值,在绘制动画效果时使用
  • axes : 此 Artist 对象所在的 Axes 对象,可能为 None
  • clip_box : 对象的裁剪框
  • clip_on : 是否裁剪
  • clip_path : 裁剪的路径
  • contains : 判断指定点是否在对象上的函数
  • figure : 所在的 Figure 对象,可能为 None
  • label : 文本标签
  • picker : 控制 Artist 对象选取
  • transform : 控制偏移旋转
  • visible : 是否可见
  • zorder : 控制绘图顺序

Artist 对象的所有属性都通过相应的 get* 和 set* 函数进行读写,例如下面的语句将 alpha 属性设置为当前值的一半:

>>> fig.set_alpha(0.5*fig.get_alpha())

如果你想用一条语句设置多个属性的话,可以使用 set 函数:

>>> fig.set(alpha=0.5, zorder=2)

使用前面介绍的 matplotlib.pyplot.getp 函数可以方便地输出 Artist 对象的所有属性名和值。

>>> plt.getp(fig.patch)
 aa = True
 alpha = 1.0
 animated = False
 antialiased or aa = True
 ... ...

Figure 容器

现在我们知道如何观察和修改已知的某个 Artist 对象的属性,接下来要解决如何找到指定的 Artist 对象。前面我们介绍过 Artist 对象有容器类型和简单类型两种,这一节让我们来详细看看容器类型的内容。

最大的 Artist 容器是 matplotlib.figure.Figure,它包括组成图表的所有元素。图表的背景是一个 Rectangle 对象,用 Figure.patch 属性表示。当你通过调用 add_subplot 或者 add_axes 方法往图表中添加轴(子图时),这些子图都将添加到 Figure.axes 属性中,同时这两个方法也返回添加进 axes 属性的对象,注意返回值的类型有所不同,实际上 AxesSubplot 是 Axes 的子类。

>>> fig = plt.figure()
>>> ax1 = fig.add_subplot(211)
>>> ax2 = fig.add_axes([0.1, 0.1, 0.7, 0.3])
>>> ax1
<matplotlib.axes.AxesSubplot object at 0x056BCA90>
>>> ax2
<matplotlib.axes.Axes object at 0x056BC910>
>>> fig.axes
[<matplotlib.axes.AxesSubplot object at 0x056BCA90>,
<matplotlib.axes.Axes object at 0x056BC910>]

为了支持 pylab 中的 gca() 等函数,Figure 对象内部保存有当前轴的信息,因此不建议直接对 Figure.axes 属性进行列表操作,而应该使用 add_subplot, add_axes, delaxes 等方法进行添加和删除操作。但是使用 for 循环对 axes 中的每个元素进行操作是没有问题的,下面的语句打开所有子图的栅格。

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

Figure 对象可以拥有自己的文字、线条以及图像等简单类型的 Artist。缺省的坐标系统为像素点,但是可以通过设置 Artist 对象的 transform 属性修改坐标系的转换方式。最常用的 Figure 对象的坐标系是以左下角为坐标原点(0,0),右上角为坐标(1,1)。下面的程序创建并添加两条直线到 fig 中:

>>> from matplotlib.lines import Line2D
>>> fig = plt.figure()
>>> line1 = Line2D([0,1],[0,1], transform=fig.transFigure, figure=fig, color="r")
>>> line2 = Line2D([0,1],[1,0], transform=fig.transFigure, figure=fig, color="g")
>>> fig.lines.extend([line1, line2])
>>> fig.show()

在 Figure 对象中手工绘制直线

注意为了让所创建的 Line2D 对象使用 fig 的坐标,我们将 fig.TransFigure 赋给 Line2D 对象的 transform 属性;为了让 Line2D 对象知道它是在 fig 对象中,我们还设置其 figure 属性为 fig;最后还需要将创建的两个 Line2D 对象添加到 fig.lines 属性中去。

Figure 对象有如下属性包含其它的 Artist 对象:

  • axes : Axes 对象列表
  • patch : 作为背景的 Rectangle 对象
  • images : FigureImage 对象列表,用来显示图片
  • legends : Legend 对象列表
  • lines : Line2D 对象列表
  • patches : patch 对象列表
  • texts : Text 对象列表,用来显示文字

Axes 容器

Axes 容器是整个 matplotlib 库的核心,它包含了组成图表的众多 Artist 对象,并且有许多方法函数帮助我们创建、修改这些对象。和 Figure 一样,它有一个 patch 属性作为背景,当它是笛卡尔坐标时,patch 属性是一个 Rectangle 对象,而当它是极坐标时,patch 属性则是 Circle 对象。例如下面的语句设置 Axes 对象的背景颜色为绿色:

>>> fig = plt.figure()
>>> ax = fig.add_subplot(111)
>>> ax.patch.set_facecolor("green")

当你调用 Axes 的绘图方法(例如 plot),它将创建一组 Line2D 对象,并将所有的关键字参数传递给这些 Line2D 对象,并将它们添加进 Axes.lines 属性中,最后返回所创建的 Line2D 对象列表:

>>> x, y = np.random.rand(2, 100)
>>> line, = ax.plot(x, y, "-", color="blue", linewidth=2)
>>> line
<matplotlib.lines.Line2D object at 0x03007030>
>>> ax.lines
[<matplotlib.lines.Line2D object at 0x03007030>]

注意 plot 返回的是一个 Line2D 对象的列表,因为我们可以传递多组 X,Y 轴的数据,一次绘制多条曲线。

与 plot 方法类似,绘制直方图的方法 bar 和绘制柱状统计图的方法 hist 将创建一个 Patch 对象的列表,每个元素实际上都是 Patch 的子类 Rectangle,并且将所创建的 Patch 对象都添加进 Axes.patches 属性中:

>>> ax = fig.add_subplot(111)
>>> n, bins, rects = ax.hist(np.random.randn(1000), 50, facecolor="blue")
>>> rects
<a list of 50 Patch objects>
>>> rects[0]
<matplotlib.patches.Rectangle object at 0x05BC2350>
>>> ax.patches[0]
<matplotlib.patches.Rectangle object at 0x05BC2350>

一般我们不会直接对 Axes.lines 或者 Axes.patches 属性进行操作,而是调用 add_line 或者 add_patch 等方法,这些方法帮助我们完成许多属性设置工作:

&gt;&gt;&gt; fig = plt.figure()
&gt;&gt;&gt; ax = fig.add_subplot(111)
&gt;&gt;&gt; rect = matplotlib.patches.Rectangle((1,1), width=5, height=12)
&gt;&gt;&gt; print rect.get_axes() # rect 的 axes 属性为空
None
&gt;&gt;&gt; rect.get_transform() # rect 的 transform 属性为缺省值
BboxTransformTo(Bbox(array([[  1.,   1.],
 [  6.,  13.]])))
&gt;&gt;&gt; ax.add_patch(rect) # 将 rect 添加进 ax
&lt;matplotlib.patches.Rectangle object at 0x05C34E50&gt;
&gt;&gt;&gt; rect.get_axes() # 于是 rect 的 axes 属性就是 ax
&lt;matplotlib.axes.AxesSubplot object at 0x05C09CB0&gt;
&gt;&gt;&gt; # rect 的 transform 属性和 ax 的 transData 相同
&gt;&gt;&gt; rect.get_transform()
... # 太长,省略
&gt;&gt;&gt; ax.transData
... # 太长,省略
&gt;&gt;&gt; ax.get_xlim() # ax 的 X 轴范围为 0 到 1,无法显示完整的 rect
(0.0, 1.0)
&gt;&gt;&gt; ax.dataLim._get_bounds() # 数据的范围和 rect 的大小一致
(1.0, 1.0, 5.0, 12.0)
&gt;&gt;&gt; ax.autoscale_view() # 自动调整坐标轴范围
&gt;&gt;&gt; ax.get_xlim() # 于是 X 轴可以完整显示 rect
(1.0, 6.0)
&gt;&gt;&gt; plt.show()

通过上面的例子我们可以看出,add_patch 方法帮助我们设置了 rect 的 axes 和 transform 属性。

下面详细列出 Axes 包含各种 Artist 对象的属性:

  • artists : Artist 对象列表
  • patch : 作为 Axes 背景的 Patch 对象,可以是 Rectangle 或者 Circle
  • collections : Collection 对象列表
  • images : AxesImage 对象列表
  • legends : Legend 对象列表
  • lines : Line2D 对象列表
  • patches : Patch 对象列表
  • texts : Text 对象列表
  • xaxis : XAxis 对象
  • yaxis : YAxis 对象

下面列出 Axes 的创建 Artist 对象的方法:

Axes 的方法所创建的对象添加进的列表
annotateAnnotatetexts
barsRectanglepatches
errorbarLine2D, Rectanglelines,patches
fillPolygonpatches
histRectanglepatches
imshowAxesImageimages
legendLegendlegends
plotLine2Dlines
scatterPolygonCollectionCollections
textTexttexts

下面以绘制散列图(scatter) 为例,验证一下:

>>> fig = plt.figure()
>>> ax = fig.add_subplot(111)
>>> t = ax.scatter(np.random.rand(20), np.random.rand(20))
>>> t # 返回值为 CircleCollection 对象
<matplotlib.collections.CircleCollection object at 0x06004230>
>>> ax.collections # 返回的对象已经添加进了 collections 列表中
[<matplotlib.collections.CircleCollection object at 0x06004230>]
>>> fig.show()
>>> t.get_sizes() # 获得 Collection 的点数
20

用 scatter 函数绘制散列图

Axis 容器

Axis 容器包括坐标轴上的刻度线、刻度文本、坐标网格以及坐标轴标题等内容。刻度包括主刻度和副刻度,分别通过 Axis.get_major_ticks 和 Axis.get_minor_ticks 方法获得。每个刻度线都是一个 XTick 或者 YTick 对象,它包括实际的刻度线和刻度文本。为了方便访问刻度线和文本,Axis 对象提供了 get_ticklabels 和 get_ticklines 方法分别直接获得刻度线和刻度文本:

&gt;&gt;&gt; pl.plot([1,2,3],[4,5,6])
[&lt;matplotlib.lines.Line2D object at 0x0AD3B670&gt;]
&gt;&gt;&gt; pl.show()
&gt;&gt;&gt; axis = pl.gca().xaxis
>>> axis.get_ticklocs() # 获得刻度的位置列表
array([ 1\. ,  1.5,  2\. ,  2.5,  3\. ])
>>> axis.get_ticklabels() # 获得刻度标签列表
<a list of 5 Text major ticklabel objects>
>>> [x.get_text() for x in axis.get_ticklabels()] # 获得刻度的文本字符串
[u'1.0', u'1.5', u'2.0', u'2.5', u'3.0']
>>> axis.get_ticklines() # 获得主刻度线列表,图的上下刻度线共 10 条
<a list of 10 Line2D ticklines objects>
>>> axis.get_ticklines(minor=True) # 获得副刻度线列表
<a list of 0 Line2D ticklines objects>

获得刻度线或者刻度标签之后,可以设置其各种属性,下面设置刻度线为绿色粗线,文本为红色并且旋转 45 度:

&gt;&gt;&gt; for label in axis.get_ticklabels():
...   label.set_color("red")
...   label.set_rotation(45)
...   label.set_fontsize(16)
...
&gt;&gt;&gt; for line in axis.get_ticklines():
...   line.set_color("green")
...   line.set_markersize(25)
...   line.set_markeredgewidth(3)

最终的结果图如下:

手工配置 X 轴的刻度线和刻度文本的样式

上面的例子中,获得的副刻度线列表为空,这是因为用于计算副刻度的对象缺省为 NullLocator,它不产生任何刻度线;而计算主刻度的对象为 AutoLocator,它会根据当前的缩放等配置自动计算刻度的位置:

>>> axis.get_minor_locator() # 计算副刻度的对象
<matplotlib.ticker.NullLocator instance at 0x0A014300>
>>> axis.get_major_locator() # 计算主刻度的对象
<matplotlib.ticker.AutoLocator instance at 0x09281B20>

我们可以使用程序为 Axis 对象设置不同的 Locator 对象,用来手工设置刻度的位置;设置 Formatter 对象用来控制刻度文本的显示。下面的程序设置 X 轴的主刻度为 pi/4,副刻度为 pi/20,并且主刻度上的文本以 pi 为单位:

# -*- coding: utf-8 -*-
import matplotlib.pyplot as pl
from matplotlib.ticker import MultipleLocator, FuncFormatter
import numpy as np
x = np.arange(0, 4*np.pi, 0.01)
y = np.sin(x)
pl.figure(figsize=(8,4))
pl.plot(x, y)
ax = pl.gca()

def pi_formatter(x, pos):
  """
 比较罗嗦地将数值转换为以 pi/4 为单位的刻度文本
 """
  m = np.round(x / (np.pi/4))
  n = 4
  if m%2==0: m, n = m/2, n/2
  if m%2==0: m, n = m/2, n/2
  if m == 0:
    return "0"
  if m == 1 and n == 1:
    return "$\pi$"
  if n == 1:
    return r"$%d \pi$" % m
  if m == 1:
    return r"$\frac{\pi}{%d}$" % n
  return r"$\frac{%d \pi}{%d}$" % (m,n)

# 设置两个坐标轴的范围
pl.ylim(-1.5,1.5)
pl.xlim(0, np.max(x))

# 设置图的底边距
pl.subplots_adjust(bottom = 0.15)

pl.grid() #开启网格

# 主刻度为 pi/4
ax.xaxis.set_major_locator( MultipleLocator(np.pi/4) )

# 主刻度文本用 pi_formatter 函数计算
ax.xaxis.set_major_formatter( FuncFormatter( pi_formatter ) )

# 副刻度为 pi/20
ax.xaxis.set_minor_locator( MultipleLocator(np.pi/20) )

# 设置刻度文本的大小
for tick in ax.xaxis.get_major_ticks():
  tick.label1.set_fontsize(16)
pl.show()

关于刻度的定位和文本格式的东西都在 matplotlib.ticker 中定义,程序中使用到如下两个类:

  • MultipleLocator : 以指定值的整数倍为刻度放置刻度线
  • FuncFormatter : 使用指定的函数计算刻度文本,他会传递给所指定的函数两个参数:刻度值和刻度序号,程序中通过比较笨的办法计算出刻度值所对应的刻度文本

此外还有很多预定义的 Locator 和 Formatter 类,详细内容请参考相应的 API 文档。

手工配置 X 轴的刻度线的位置和文本,并开启副刻度

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文