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的缺省配置文件中所使用的字体无法正确显示中文。为了让图表能正确显示中文,可以有几种解决方案。
  1. 在程序中直接指定字体。
  2. 在程序开头修改配置字典rcParams。
  3. 修改配置文件。
matplotlib输出图象的中文显示问题

上面那个link里的修改matplotlibrc方式,我试了好几次都没成功。能work的一个比较简便粗暴的方式(但不知道有没有副作用)是

  1. 找到字体目录YOURPYTHONHOME\Lib\site-packages\matplotlib\mpl-data\fonts\ttf下的Vera.ttf。这里我们用中文楷体(可以从windows/system32/fonts拷贝过来,对于win8字体文件不是ttf的可以从网上下一个微软雅黑),直接张贴到前面的ttf目录下,然后更名为Vera.ttf。
  2. 中文字符串用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=)线条含义
bblue 蓝.point
ggreen 绿ocircle
rred 红xx-mark
ccyan 青+plus
mmagenta 品红*star
yyellow 黄ssquare
kblack 黑ddiamond
wwhite 白vtriangle (down)
^triangle (up)
<triangle (left)
>triangle (right)
ppentagram 五角星
hhexagram 六角星
-solid
:dotted
-.dashdot
dashed

友情链接:
python之matplotlib
Python--matplotlib绘图可视化知识点整理
pythonmatplotlib详解
Python图表绘制:matplotlib绘图库入门
Python–matplotlib(持续更新)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坦笑&&life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值