matplotlib-绘制精美的图表



matplotlib-绘制精美的图表

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()
_images/pyplot_simple_plot.png

调用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像素。

可是用工具栏中的保存button保存下来的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之后,用keyword參数指定各种属性:

  • 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

通过这样的方法我们能够非常easy地查看对象的属性和它们之间的包括关系,找到须要配置的属性。

绘制多轴图

一个画图对象(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()
_images/pyplot_subplot01.png

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

假设希望某个轴占领整个行或者列的话,能够例如以下调用subplot:

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

将Figure分为三个子图区域

当画图对象中有多个轴的时候,能够通过工具栏中的Configure Subplotsbutton。交互式地调节轴之间的间距和轴与边框之间的距离。假设希望在程序中调节的话,能够调用subplots_adjust函数,它有left, right, bottom, top, wspace, hspace等几个keyword參数。这些參数的值都是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'

假设你用文本编辑器打开此配置文件的话。你会发现它实际上是定义了一个字典。为了对众多的配置进行区分,keyword能够用点分开。

配置文件的读入能够使用 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()
_images/pyplot_artist01.png

在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对象。并将全部的keyword參数传递给这些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等方法,这些方法帮助我们完毕很多属性设置工作:

>>> fig = plt.figure()
>>> ax = fig.add_subplot(111)
>>> rect = matplotlib.patches.Rectangle((1,1), width=5, height=12)
>>> print rect.get_axes() # rect的axes属性为空
None
>>> rect.get_transform() # rect的transform属性为缺省值
BboxTransformTo(Bbox(array([[  1.,   1.],
       [  6.,  13.]])))
>>> ax.add_patch(rect) # 将rect加入进ax
<matplotlib.patches.Rectangle object at 0x05C34E50>
>>> rect.get_axes() # 于是rect的axes属性就是ax
<matplotlib.axes.AxesSubplot object at 0x05C09CB0>
>>> # rect的transform属性和ax的transData同样
>>> rect.get_transform()
... # 太长,省略
>>> ax.transData
... # 太长,省略
>>> ax.get_xlim() # ax的X轴范围为0到1,无法显示完整的rect
(0.0, 1.0)
>>> ax.dataLim._get_bounds() # 数据的范围和rect的大小一致
(1.0, 1.0, 5.0, 12.0)
>>> ax.autoscale_view() # 自己主动调整坐标轴范围
>>> ax.get_xlim() # 于是X轴能够完整显示rect
(1.0, 6.0)
>>> 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的方法 所创建的对象 加入进的列表
annotate Annotate texts
bars Rectangle patches
errorbar Line2D, Rectangle lines,patches
fill Polygon patches
hist Rectangle patches
imshow AxesImage images
legend Legend legends
plot Line2D lines
scatter PolygonCollection Collections
text Text texts

以下以绘制散列图(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
_images/pyplot_artist02.png

用scatter函数绘制散列图

Axis容器

Axis容器包含坐标轴上的刻度线、刻度文本、坐标网格以及坐标轴标题等内容。刻度包含主刻度和副刻度,分别通过Axis.get_major_ticks和Axis.get_minor_ticks方法获得。

每一个刻度线都是一个XTick或者YTick对象,它包含实际的刻度线和刻度文本。

为了方便訪问刻度线和文本,Axis对象提供了get_ticklabels和get_ticklines方法分别直接获得刻度线和刻度文本:

>>> pl.plot([1,2,3],[4,5,6])
[<matplotlib.lines.Line2D object at 0x0AD3B670>]
>>> pl.show()
>>> 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度:

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

终于的结果图例如以下:

_images/pyplot_axis01.png

手工配置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文档。


原文地址:https://www.cnblogs.com/gcczhongduan/p/5341756.html