Python处理数据方向之Matplotlib
前言
Matplotlib,全称“Matlab plotting library”,是基于Python语言的开源项目, 旨在为Python提供一个数据绘图包。它是数字的-NumPy库的数学扩展,是Python中绘制二维和三维图表的数据可视化工具。
matplotlib 是python最著名的绘图库,它提供了一整套和matlab相似的命令API,十分适合交互式地行制图。而且也可以方便地将它作为绘图控件,嵌入GUI应用程序中。
matplotlib的对象体系严谨而有趣,为使用者提供了巨大的发挥空间。用户在熟悉了核心对象之后,可以轻易的定制图像。matplotlib的对象体系也是计算机图形学的一个优秀范例。
它的文档相当完备,并且Gallery页面中有上百幅缩略图,打开之后都有源程序。因此如果你需要绘制某种类型的图,只需要在这个页面中浏览/复制/粘贴一下,基本上都能搞定。
在Linux下比较著名的数据图工具还有gnuplot,这个是免费的,Python有一个包可以调用gnuplot,但是语法比较不习惯,而且画图质量不高。
而 Matplotlib则比较强:Matlab的语法、python语言、latex的画图质量(还可以使用内嵌的latex引擎绘制的数学公式)。
Matplotlib的绘画接口分为三种:pyplot,面向当前图;axes,面向对象;Pylab,沿用 matlab 风格。
Matplotlib中的所有内容都按层次结构组织,层次结构的顶部是由matplotlib提供的matplotlb“状态机环境”——pyplot模块,仅用于图形创建等少数功能,用户显式创建并跟踪图形和轴对象。
层次结构的下一层是面向对象界面的第一层,在此级别,使用pyplot创建图形,通过这些图形可以创建一个或多个轴对象,使用基础函数将绘图元素(线条、图像、文本等)添加到当前图形中的当前轴。
发起人
matplotlib使用numpy进行数组运算,并调用一系列其他的Python库来实现硬件交互。matplotlib的核心是一套由对象构成的绘图API
matplotlib项目是由John D. Hunter发起的。John D. Hunter由于癌症于2017年过世,但他发为社区作出的无比贡献将永远留存。
必备工具
你需要安装Python, numpy和matplotlib。(可以到python.org下载Python编译器。相关Python包的安装,请自行上网查阅)
matplotlib的官网是: http://matplotlib.org/ 官网有丰富的图例和文档说明。
matplotlib在github的地址为:https://github.com/matplotlib 欢迎有兴趣的开发者fork。
Matplotlib.pyplot快速绘图
快速绘图和面向对象方式绘图
matplotlib实际上是一套面向对象的绘图库,它所绘制的图表中的每个绘图元素,例如线条Line2D、文字Text、刻度等在内存中都有一个对象与之对应。
matplotlib是受MATLAB的启发构建的。MATLAB是数据绘图领域广泛使用的语言和工具。MATLAB语言是面向过程的。利用函数的调用,MATLAB中可以轻松的利用一行命令来绘制直线,然后再用一系列的函数调整结果。
matplotlib有一套完全仿照MATLAB的函数形式的绘图接口,在matplotlib.pyplot模块中。这套函数接口方便MATLAB用户过度到matplotlib包。下面,我们调用该模块绘制一条直线。
为了方便快速绘图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()方法实现真正的绘图。
可以在Ipython中输入类似"plt.plot??"的命令查看pyplot模块的函数是如何对各种绘图对象进行包装的。
配置属性
matplotlib所绘制的图表的每个组成部分都和一个对象对应,我们可以通过调用这些对象的属性设置方法set_*()或者pyplot模块的属性设置函数setp()设置它们的属性值。
因为matplotlib实际上是一套面向对象的绘图库,因此也可以直接获取对象的属性
配置文件
绘制一幅图需要对许多对象的属性进行配置,例如颜色、字体、线型等等。我们在绘图时,并没有逐一对这些属性进行配置,许多都直接采用了matplotlib的缺省配置。
matplotlib将这些缺省配置保存在一个名为“matplotlibrc”的配置文件中,通过修改配置文件,我们可以修改图表的缺省样式。配置文件的读入可以使用rc_params(),它返回一个配置字典;在matplotlib模块载入时会调用rc_params(),并把得到的配置字典保存到rcParams变量中;matplotlib将使用rcParams字典中的配置进行绘图;用户可以直接修改此字典中的配置,所做的改变会反映到此后创建的绘图元素。
准备
格式调整 & 自定义设置
# 导入matplotlib库中的pyplot
import matplotlib as mpl
import matplotlib.pyplot as plt
# 解决中文乱码,可自行修改期望字体
plt.rcParams['font.sans-serif']='SimHei'
mpl.rcParams['font.family']=[Heiti SC]
# 解决负号无法显示的问题
plt.rcParams['axes.unicode_minus']=False
# 将图表以矢量图格式显示,提高清晰度
%config InlineBackend.figure_format = 'svg'
# 提高dpi,以提高图片清晰度(dpi到三百以上,效果会明显变化)
# 也可在设置figure时设置dpi
mpl.rcParams['figure.dpi']=300
# 获取figure尺寸,默认6.4 inch,4.8 inch
plt.rcParams.get('figure.figsize')
# 全局设置输出图片大小的宽m和高n
plt.rcParams['figure.figsize']=(m,n)
# 获取字体大小,默认10.0 & 设置字体大小为k
plt.rcParams.get('font.size')
plt.rcParams['font.size']=k
# 图画面板调整为白色
rc={'axes.facecolor':'white','savefig.facecolor':'white'}
mpl.rcParams.update(rc) #一次更新多个值
# 允许输出数学公式
mpl.rcParams['text.usetex']=True
# Figure自动调整格式
plt.rcParams['figure.constrained_layout.use']=True
# 隐藏坐标系,二维三维均可
plt.axis('off')
# 三维坐标轴比例伸缩
ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), np.diag([1, 1, 2, 2]))
# 去除白边
# bbox_inches = 'tight' 可去除部分白边
# pad_inches 可正可负,减小时会放大图片在画布上的占比,以达到减少白边的效果
savefig(bbox_inches = 'tight',pad_inches = -1.7)
绘制多子图(快速绘图)
Matplotlib 里的常用类的包含关系为 Figure -> Axes -> (Line2D, Text, etc.)一个Figure对象可以包含多个子图(Axes),在matplotlib中用Axes对象表示一个绘图区域,可以理解为子图。
可以使用subplot()快速绘制包含多个子图的图表,它的调用形式如下:
subplot(numRows, numCols, plotNum)
subplot将整个绘图区域等分为numRows行* numCols列个子区域,然后按照从左到右,从上到下的顺序对每个子区域进行编号,左上的子区域的编号为1。如果numRows,numCols和plotNum这三个数都小于10的话,可以把它们缩写为一个整数,例如subplot(323)和subplot(3,2,3)是相同的。subplot在plotNum指定的区域中创建一个轴对象。如果新创建的轴和之前创建的轴重叠的话,之前的轴将被删除。
subplot()返回它所创建的Axes对象,我们可以将它用变量保存起来,然后用sca()交替让它们成为当前Axes对象,并调用plot()在其中绘图。
绘制多图表(快速绘图)
如果需要同时绘制多幅图表,可以给figure()传递一个整数参数指定Figure对象的序号,如果序号所指定的Figure对象已经存在,将不创建新的对象,而只是让它成为当前的Figure对象。
import numpy as np
import matplotlib.pyplot as plt
plt.figure(1) # 创建图表1
plt.figure(2) # 创建图表2
ax1 = plt.subplot(211) # 在图表2中创建子图1
ax2 = plt.subplot(212) # 在图表2中创建子图2
x = np.linspace(0, 3, 100)
for i in xrange(5):
plt.figure(1) #❶ # 选择图表1
plt.plot(x, np.exp(i*x/3))
plt.sca(ax1) #❷ # 选择图表2的子图1
plt.plot(x, np.sin(i*x))
plt.sca(ax2) # 选择图表2的子图2
plt.plot(x, np.cos(i*x))
plt.show()
在图表中显示中文
matplotlib的缺省配置文件中所使用的字体无法正确显示中文。为了让图表能正确显示中文,可以有几种解决方案。
- 在程序中直接指定字体。
- 在程序开头修改配置字典rcParams。
- 修改配置文件。
matplotlib输出图象的中文显示问题
上面那个link里的修改matplotlibrc方式,我试了好几次都没成功。能work的一个比较简便粗暴的方式(但不知道有没有副作用)是
- 找到字体目录YOURPYTHONHOME\Lib\site-packages\matplotlib\mpl-data\fonts\ttf下的Vera.ttf。这里我们用中文楷体(可以从windows/system32/fonts拷贝过来,对于win8字体文件不是ttf的可以从网上下一个微软雅黑),直接张贴到前面的ttf目录下,然后更名为Vera.ttf。
- 中文字符串用unicode格式,例如:u’‘测试中文显示’',代码文件编码使用utf-8 加上" # coding = utf-8 "一行。
概述
Matplotlib代码库十分庞大,这可能会让初学者望而生畏。然而,大多数matplotlib都可以通过一个相当简单的概念框架和几个要点来理解。
框架之Figure、Axes、Axis:
下图引用自matplotlib官网。
- Figure可以理解为画板,可以包括多个Axes(可理解为画布);
- Axes是Axis的复数形式,表示一个Axes包含多个Axis(x轴、y轴、z轴);
- Axis 表示一个轴(x轴或y轴或z轴(3-D))
这个图来自网络,表现了Figure、Axes、Axis之间的关系,或许更清晰。
所以一般画图分为三步: 创建画板–> 创建画布–>通过坐标画图
Figure–创建画板
如下示例,创建了3个画板,之后又切到画板1。
import matplotlib.pyplot as plt
# create figure
'''
plt.figure(num=None, # 当给它一个数字时,就作为画板的编号,相当于 ID 号;当给它一个字符串时,就作为画板的名称
figsize=None, # 画板的宽、高,单位为英寸 (2.5cm)
dpi=None, # 指定在该画板上绘制的图像的分辨率,即每英寸多少个像素
facecolor=None, # 画板的背景颜色
edgecolor=None, # 画板的边框颜色
frameon=True, # 是否显示边框
FigureClass,
clear=False,
**kwargs)
'''
# 如果figure不存在,则创建,否则切到此figure
fig1 = plt.figure(1)
fig2 = plt.figure(2)
fig3 = plt.figure(3)
fig1 = plt.figure(1)
plt.show() # show
Axes–创建画布
创建画布有多种方法:
方法1:Figure.add_subplot方法
import numpy as np
import matplotlib.pyplot as plt
# create data
A1 = np.arange(1, 6) # x ∈ [1,5]
A2 = np.arange(1, 11) # x ∈ [1,10]
B = A1 ** 2
C = A1 ** 3
D = A2 ** 2
# step1: create figure
fig = plt.figure()
# step2: create axes
ax1 = fig.add_subplot(221) # 在画板上添加画布
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(212)
# step3: plot data
ax1.bar(A1, B)
ax2.scatter(A1, C)
ax3.plot(A2, D)
plt.show() # show
其效果如下:
方法2: fig.add_axes()方法
使用fig.add_axes()方法可以很容易添加子图。
import numpy as np
import matplotlib.pyplot as plt
# create data
A1 = np.arange(1, 6) # x ∈ [1,5]
A2 = np.arange(1, 11) # x ∈ [1,10]
B = A1 ** 2
C = A1 ** 3
D = A2 ** 2
# step1: create figure
fig = plt.figure()
# step2: create axes
# 左边轴从整个figure10%的地方开始,下边轴整个figure10%的地方开始,
# 宽度为整个figure的80%,高度为整个figure的80%
left,bottom,width,height = 0.1,0.1,0.8,0.8
ax1 = fig.add_axes([left,bottom,width,height]) # 在画板上添加画布
left,bottom,width,height = 0.2,0.7,0.20,0.20
ax2 = fig.add_axes([left,bottom,width,height])
left,bottom,width,height = 0.65,0.1,0.20,0.20
ax3 = fig.add_axes([left,bottom,width,height])
# step3: plot data
ax1.plot(A2, D)
ax2.bar(A1, B)
ax3.scatter(A1, C)
plt.show() # show
方法3: pyplot.subplot(nrows, ncols, index, **kwargs)
通过subplot方法创建画布后,可以直接使用plt.plot直接在当前活跃的axes上面作图。
有如下两种写法(为了方便区分,创建2张画板):
import numpy as np
import matplotlib.pyplot as plt
# create data
A1 = np.arange(1, 6) # x ∈ [1,5]
A2 = np.arange(1, 11) # x ∈ [1,10]
B = A1 ** 2
C = A1 ** 3
D = A2 ** 2
############ 写法1 ############
# step1: create figure
fig1 = plt.figure(1) # 创建画板1
# step2: create axes
ax1 = plt.subplot(221) # 在画板上添加画布,等价于ax1 = plt.gcf().subplot(221)
# 其中 .gcf() 的作用是获取当前 figure, 即 get current figure;
ax2 = plt.subplot(222)
ax3 = plt.subplot(212)
# step3: plot data
ax1.bar(A1, B)
ax2.scatter(A1, C)
ax3.plot(A2, D)
############ 写法2 ############
# step1: create figure
fig2 = plt.figure(2) # 创建画板2
# step2: create axes and plot
plt.subplot(221) # 在画板上添加画布
plt.bar(A1, B) # 直接使用plt.plot直接在当前活跃的axes上面作图,plt.plot等价于plt.gca().plot()
# 其中.gca() 就是获取当前 axes,即 get current axes
plt.subplot(222)
plt.scatter(A1, C)
plt.subplot(212)
plt.plot(A2, D)
plt.show() # show
方法3同样可以画出方法1一样的图。
方法4:fig, axes = pyplot.subplots()
subplots与subplot区别:
- subplots() 既创建了一个包含子图区域的画布axes,又创建了一个 figure 图形对象,而 subplot() 只是创建一个包含子图区域的画布axes。
- subplots() 只能创建nRows * nCols 的规则画布,而subplot()可以创建不规则画布(如:下图与方法1画图的区别,也可见参考3)
import numpy as np
import matplotlib.pyplot as plt
# create data
A1 = np.arange(1, 6) # x ∈ [1,5]
A2 = np.arange(1, 11) # x ∈ [1,10]
B = A1 ** 2
C = A1 ** 3
D = A2 ** 2
# step1: create fig and create axes
fig, ax = plt.subplots(2,2) # 创建画板并添加画布
# ax0, ax1, ax2, ax3 = ax.ravel() # 将数组多维度拉成一维数组
# step2: plot data
ax[0][0].bar(A1, B)
ax[0][1].scatter(A1, C)
ax[1][0].plot(A2, D)
plt.show() # show
其结果如下:
Axis–坐标轴操作
下图展示的是matplotlib库Axis的一些操作。
上图的函数列表如下:
函数 | 作用 |
---|---|
ax.plot | 折线图 |
ax.scatter | 画散点图 |
ax.bar | 画柱状图 |
ax.set_title | 设置图标标题 |
ax.set_xlable | 给x坐标轴加上标签 |
ax.set_ylable | 给y坐标轴加上标签 |
ax.set_xticks | 轴的x刻度 |
ax.set_yticks | 轴的y刻度 |
ax.text | 添加文本框 |
ax.grid | 添加网格线 |
颜色与线条:
颜色标记(c=) | 颜色含义 | 线条标记(marker=) | 线条含义 |
---|---|---|---|
b | blue 蓝 | . | point |
g | green 绿 | o | circle |
r | red 红 | x | x-mark |
c | cyan 青 | + | plus |
m | magenta 品红 | * | star |
y | yellow 黄 | s | square |
k | black 黑 | d | diamond |
w | white 白 | v | triangle (down) |
^ | triangle (up) | ||
< | triangle (left) | ||
> | triangle (right) | ||
p | pentagram 五角星 | ||
h | hexagram 六角星 | ||
- | solid | ||
: | dotted | ||
-. | dashdot | ||
– | dashed |
友情链接:
python之matplotlib
Python--matplotlib绘图可视化知识点整理
python之matplotlib详解
Python图表绘制:matplotlib绘图库入门
Python–matplotlib(持续更新)