详解ipython中matplotlib的使用

matplotlib实际上是一套面向对象的绘图库,它所绘制的图表中的每个绘图元素,例如线条line2d、文字text、刻度等在内存中都有一个对象与之对应。为了方便快速绘图matplotlib通过pyplot模块提供了一套和matlab类似的绘图api,将众多绘图对象所构成的复杂结构隐藏在这套api内部。我们只需要调用pyplot模块所提供的函数就可以实现快速绘图以及设置图表的各种细节。pyplot模块虽然用法简单,但不适合在较大的应用程序中使用。为了将面向对象的绘图库包装成只使用函数的调用接口,pyplot模块的内部保存了当前图表以及当前子图等信息。当前的图表和子图可以使用plt.gcf()和plt.gca()获得,分别表示”get current figure”和”get current axes”。在pyplot模块中,许多函数都是对当前的figure或axes对象进行处理,比如说:plt.plot()实际上会通过plt.gca()获得当前的axes对象ax,然后再调用ax.plot()方法实现真正的绘图。

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

可以在ipython中输入类似”plt.plot??”的命令查看pyplot模块的函数是如何对各种绘图对象进行包装的。

1、pyplot.plot(*args, **kwargs)

这个函数有两个参数,一个可变参数,一个命名参数。可变参数可以指定三个参数,x,y序列和线条格式字符串,下面的例子是一些常用的搭配

plot(x, y) # plot x and y using default line style and color
plot(x, y, ‘bo’) # plot x and y using blue circle markers
plot(y) # plot y using x as index array 0..n-1
plot(y, ‘r+’) # ditto, but with red plusses
如果没有使用命名参数,那么可以设置任意组的x,y,格式字符串,例如:a.plot(x1, y1, ‘g^’, x2, y2, ‘g-‘)
plot的返回值类型是matplotlib.lines.line2d object
如果不指定plot会采用默认的线条和颜色,下面给出线条和颜色的可设值
线条值================ ===============================
character description
================ ===============================
“’-‘“ solid line style 实线
“’–‘“ dashed line style 虚线
“’-.’“ dash-dot line style 虚点线
“’:’“ dotted line style 点线
“’.’“ point marker 圆点作点
“’,’“ pixel marker
“’o’“ circle marker 蓝色圆圈作点
“’v’“ triangle_down marker 下三角作点
“^_^ _^” triangle_up marker 上三角作点
“”“ triangle_right marker
“’1’“ tri_down marker
“’2’“ tri_up marker
“’3’“ tri_left marker
“’4’“ tri_right marker
“’s’“ square marker
“’p’“ pentagon marker
“’*’“ star marker
“’h’“ hexagon1 marker
“’h’“ hexagon2 marker
“’+’“ plus marker
“’x’“ x marker
“’d’“ diamond marker
“’d’“ thin_diamond marker
“’|’“ vline marker
“’_’“ hline marker
================ ===============================
颜色值
========== ========
character color
========== ========
‘b’ blue
‘g’ green
‘r’ red
‘c’ cyan
‘m’ magenta
‘y’ yellow
‘k’ black
‘w’ white
========== ========
命名参数可以用来设置线条的属性,每个属性都有一个set_…的方法,可以用来设置线条的标签,线宽等等

plt还有 一个rc_params 函数,它返回配置字典rcparams

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

当前路径 : 程序的当前路径

用户配置路径 : 通常为 home/.matplotlib/,可以通过环境变量matplotlibrc修改

系统配置路径 : 保存在 matplotlib的安装目录下的 mpl-data 下

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

>>> import matplotlib>>> matplotlib.get_configdir()’c:\\documents and settings\\suntp\\.matplotlib’

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

matplotlib.matplotlib_fname()
out[2]: ‘c:\\programdata\\anaconda3\\lib\\site-packages\\matplotlib\\mpl-data\\matplotlibrc’由于在当前路径和用户配置路径中都没有找到位置文件,因此最后使用的是系统配置路径下的配置文件。在matplotlib模块载入的时候会调用rc_params,并把得到的配置字典保存到rcparams变量中

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

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.0animated = false
antialiased or aa = true
axes = axes(0.125,0.1;0.775×0.8)
… …

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

指定属性名:返回对象的指定属性的值

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

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

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

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

>>> plt.getp(f, “axes”)
[]>>> plt.gca()

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

>>> alllines = plt.getp(plt.gca(), “lines”)>>> alllines
>>> 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()

图5.3 将figure分为三个子图区域

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

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
[]>>> line

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

xaxis的label属性是一个text对象:

>>> ax.xaxis.label

而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
>>> ax2
>>> fig.axes
[,]

为了支持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()

图5.4 在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
>>> ax.lines
[]

注意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
>>> rects[0]
>>> ax.patches[0]

一般我们不会直接对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

>>> rect.get_axes() # 于是rect的axes属性就是ax

>>> # 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的方法所创建的对象添加进的列表annotateannotatetextsbarsrectanglepatcheserrorbarline2d, rectanglelines,patchesfillpolygonpatcheshistrectanglepatchesimshowaxesimageimageslegendlegendlegendsplotline2dlinesscatterpolygoncollectioncollectionstexttexttexts

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

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

图5.6 手工配置x轴的刻度线和刻度文本的样式

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

>>> axis.get_minor_locator() # 计算副刻度的对象
>>> axis.get_major_locator() # 计算主刻度的对象

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

# -*- coding: utf-8 -*-import matplotlib.pyplot as plfrom matplotlib.ticker import multiplelocator, funcformatterimport 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/4ax.xaxis.set_major_locator( multiplelocator(np.pi/4) )# 主刻度文本用pi_formatter函数计算ax.xaxis.set_major_formatter( funcformatter( pi_formatter ) )# 副刻度为pi/20ax.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文档。

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

以上就是详解ipython中matplotlib的使用的详细内容,更多请关注 第一php社区 其它相关文章!

Posted in 未分类