本文主要是介绍MPL学习手册A001-matplotlib面向对象绘图快感初体验,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本篇将:
- 引入mpl面向对象绘图的几个重要概念和对象;
- 采用纯面向对象的绘图方式绘制一个基本图形;
- 与函数式绘图做一些简单比较;
- 自定义一个figure类,实现图形基本格式的统一定制;
- 提供一个有更多对象的示例供有兴趣者研究。
matplotlib设计了两种绘图模式:
- pyplot模块的函数式绘图
- object-oriented的面向对象,简称OO。
什么是mpl的对象?
简单地说,mpl对我们绘图中要用到的一些元素进行了分级、分组、归类,这些元素就是对象。
比如,最基本的图形对象—Figure,坐标系对象—Axes,坐标轴对象Axis,Axis上的XTick YTick(刻度)对象。
mpl提供了一些python类,class,用来抽象、描述、定制这些对象。
**小提示:**根据Python命名规范,Class名用首字母大写的单词命名,如果需要多个单词,接着写,首字母大写以区分单词,如MyFigA;变量名全用小写字母的单词,单词之间用短下划线连接。比如,XTick就是一个Class类名,而如axes_a这样的应该是一个变量名。我们在命名时也应该遵循这个规范。
约定
有些对象、概念,翻译后反而不便于理解,所以我们约定如下:
- **Figure,**图形类Class;
- Axes,是Axis的复数形式,意即2个以上的坐标轴,有很多地方也译为坐标轴,这容易混淆。在基础篇中,我们只讨论2D平面坐标,Axes就是平面坐标系。而Axis则是这个坐标系中的两条轴线之一,用x, y表示。Axes是坐标系,它实际代表一个矩形区域。
- Canvas, 画布,绘图时我们都需要附加一个画布对象,Photoshop也是如此,至于为什么要这么一个画布对象,我们后面再讨论,我们先记住,Figure必须附加到一个Canvas。
你暂时不需要完全理解每行代码,你只需要照着体验一下纯面向对象绘图和函数式绘图的区别。
创建一个空白的Figure
mpl提供了一个Figure类,实例化这个类即可创建一个figure实例。Figure类的调用方法如下:
class matplotlib.figure.Figure(figsize=None, dpi=None, facecolor=None, edgecolor=None, linewidth=0.0, frameon=None, subplotpars=None, tight_layout=None, constrained_layout=None)
你甚至不需要提供任何参数,mpl会使用默认参数创建一个图形。
启动jupyter lab,新建一个ipynb文件,输入如下代码:
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.figure import Figure
from matplotlib.axes import Axes
import numpy as np
from numpy import math#实例化Figure类,并将实例赋给变量fig
fig =Figure()#实例化一个FigureCanvasAgg画布
#并附加到前面创建的Figure实例fig上
canvas = FigureCanvasAgg(fig)#将图形渲染到缓存
s, (width, height) = canvas.print_to_buffer() from PIL import Image
#调用PIL库将缓存中的数据渲染为图像
im = Image.frombytes("RGBA", (width, height), s)#调用系统图片查看器查看图像
# 在本例中Figuer中还什么都没有仅是一个空白区域。
im.show() #如果需要,你还可以将绘图保存为磁盘文件
canvas.print_figure('tth001.jpg')
运行它,会自动打开系统默认的图片查看器,显示生成的图片。因为现在图上还什么都没有,所以仅一块空白的区域。
**但这恰是Figure对象的本质,**它就是一个顶级容器,一块矩形区域,用来放置后面的元素。
创建一个Axes
mpl提供了一个Axes类用于创建坐标系。
class matplotlib.axes.Axes(fig, rect, facecolor=None, frameon=True, sharex=None, sharey=None, label='', xscale=None, yscale=None, **kwargs
)
Axes首先也是一个矩形区域,它是Figure的一个子区域。一个Figure可以划分为多个Axes子区域。
Axes至少需要两个参数 fig, rect。fig是轴所在的figure,rect是定义矩形区域的左、底、宽、高的浮点数列表,如[0.1,0.1,0.5,0.5]。它的单位是相对于figure这个矩形区域的分数,用0-1之间的小数表示。
在上面的代码中添加如下代码:
rect = [0.1,0.1,0.8,0.8]
ax = Axes(fig,rect)
fig.add_axes(ax)
完整代码如下:
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.figure import Figure
from matplotlib.axes import Axes
import numpy as np
from numpy import math#实例化Figure类,并将实例赋给变量fig
fig =Figure()#实例化一个FigureCanvasAgg画布
#并附加到前面创建的Figure实例fig上
canvas = FigureCanvasAgg(fig)#创建一个axes对象
rect = [0.1,0.1,0.8,0.8]
ax = Axes(fig,rect)
fig.add_axes(ax)
s, (width, height) = canvas.print_to_buffer()
from PIL import Image#调用PIL库将缓存中的数据渲染为图像
im = Image.frombytes("RGBA", (width, height), s)
#调用系统图片查看器查看图像
# 在本例中Figuer中还什么都没有仅是一个空白区域。im.show()
#如果需要,你还可以将绘图保存为磁盘文件
#canvas.print_figure('tth001.jpg')
这时我们就能看到,在前面的图形中有了一个坐标系。
在这个Figure中我们看不出来figure和Axes的位置关系。
pyplot函数绘图很简单,但很模糊
我们使用函数式绘图绘制一个类似的图形,只需要3行代码。
这时,有人就要问了:你为什么要舍简求繁?
而我要反回你几个问题:
- 你知道figure必须附加到一个canvas上吗?
- 你在哪里创建canvas的?
- 你在哪里绘制的Axes?
- 如果你要修改这个Axes,让它的右边留出更多的空白,你怎么做?
- 如果Figure中有两个Axes,如ax_a,ax_b,你如何向指定的Aexs添加绘图元素?
等等,这样的问题很多。
上图的源代码请访问”Python草堂群“457079928下载。
这个figure中有两个axes,要控制不同轴的格式及其中图形元素的格式,不使用面向对象绘图,将深受对象定位和选择的困扰。
通过自定义类统一你的绘图风格
我们写论文、书籍时,一般应该保证插入图表基本风格的一致,如配色、大小、布局等的一致。
比如我准备在本系列文章中,经常采用一个图形左右两个Axes,以便对比参数不同设置的效果,同时为了便于理解不同坐标系统、不同区域,我明确标出figure的边框和底色。
为了避免做一些重复设置,简化面向对象绘图的代码,我将定义一个Figure子类,定制好基本风格,后面直接引入这个子类即可保证风格的统一,又能简化代码。
下面的代码定义了一个名为”MyFigA()"的子类,它继承了mpl的Figure类,但重设了尺寸、边框、颜色等属性。
class MyFigA(Figure):#设置一些颜色值ax_fca = (249/256,244/256,206/256)ax_fcb = (138/256,176/256,209/256)pl_cb = (8/256,89/256,156/256)pl_cr = (239/256,8/256,8/256)def __init__(self,figsize=(9.6,4.8), #在这里修改父类参数的默认值dpi=100,facecolor=(239/256,239/256,239/256),edgecolor=(82/256,101/256,155/256),linewidth=10.0,frameon=True,subplotpars=None, tight_layout=None, constrained_layout=None, ):# 子类调用父类的方法super(MyFigA, self).__init__(figsize, dpi,facecolor,edgecolor,linewidth,frameon,subplotpars,tight_layout,constrained_layout)
将上面的代码保存"tth.py"文件,后面,我们只要引用这个类,即可重复使用这个所示的Figure模板:
输出这样一个Figure,就像一个模板一样。
一个完成更多任务的纯面向对象绘图的示例
向上面Figure模板添加更多的元素,这些都是完全面向对象的方法实现的。
- 添加两个Axes;
- 为每个Axes添加了两个三角函数曲线;
- 添加风格;
- 对两个Axes及其元素赋予不同的颜色,以示区别。
最重要的,就像在现实中绘画一样,在哪个区域绘制什么?要向不同的区域添加什么样的艺术(artists)元素,自己的头脑中都非常清晰。
代码如下:
import tth
from matplotlib.axes import Axes
from numpy import math
fig = MyFigA()
canvas = FigureCanvasAgg(fig)
ax_a = Axes(fig, [0.08,0.08,0.4,0.85], facecolor=fig.ax_fca)
ax_b = Axes(fig, [0.55, 0.08,0.4,0.85], facecolor=fig.ax_fcb)
fig.add_axes(ax_a)
fig.add_axes(ax_b)
x = np.arange(0, 2*math.pi, 0.001)
y = np.sin(x)
ax_a.plot(x, y, color=fig.pl_cr)
ax_b.plot(x, y, color=fig.pl_cb)
ax_a.plot(x, np.cos(x), color='g')
ax_b.plot(x, np.cos(x), color='r')
ax_a.grid(b=True,lw=2)
ax_b.grid(b=True,lw=2)
s, (width, height) = canvas.print_to_buffer()
from PIL import Image #调用PIL
im = Image.frombytes("RGBA", (width, height), s)
im.show()
源代码请访问”Python草堂“群457079928下载。
总结:
像现实中绘画一样,自主控制matplotlib的绘图,让我们非常清楚图形的每个子区域、每个元素,谁是谁,我正在操控谁!
是不是比函数绘图一笔糊涂账要有快感呢?
下一篇,我们将解析一下matplotlib的对象结构,然后开始重点讨论Figure对象。当你透彻地理解了Fgiure,当你看Figure就像庖丁看一头牛一样时,你的matplotlib就会不知不觉地上升到一个全新的境界。
(This end.)
这篇关于MPL学习手册A001-matplotlib面向对象绘图快感初体验的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!