【matplotlib】可视化解决方案——如何正确理解pyplot和OO-API

概述

matplotlib 是一个 Python 绘图库,能够以多种硬拷贝格式和跨平台的交互式环境生成出版物质量的图形,可以用来绘制各种静态、动态、交互式的图表。matplotlib 提供了两种绘图接口:

  • 隐式 API:使用 pyplot 的 MATLAB 风格绘图接口;
  • 显式 API:使用面向对象的接口;

接下来我将会一一说明两种 API。

隐式 API

首先说一下 pyplot 模块,很多人对此有很大的误解,认为 pyplot 才是 matplotlib 库的核心,但实则不然,我们稍微深入研究一下 pyplot 库的源码,以绘制折线图为例,我们一般调用 plt.plot(),该方法的源码如下:

def plot(*args, scalex=True, scaley=True, data=None, **kwargs):  
    return gca().plot(  
        *args, scalex=scalex, scaley=scaley,  
        **({"data": data} if data is not None else {}), **kwargs)

def gca(**kwargs):  
    return gcf().gca(**kwargs)

可以看到真正执行折线图绘图指令的对象是 gcf().gca()gcf() 方法用来返回当前的 Figure 对象;而 gca() 方法返回当前的 Axes 对象。本质上还是在使用面向对象的方法。那为什么还需要 pyploy 这样的隐式 API 呢?

因为 matplotlib.pyplot 简单、直接,能够胜任我们想要解决的大多数任务。matplotlib 就是在这种类 MATLAB 的哲学思想下被设计出来的。帮助我们在绘图时减少指令的使用。甚至只需要一个指令就能完成任务(例如 plt.plot(x, y))。这样我们就不需要去思考对象、方法、属性、渲染后端、图表、画布和其他图形元素。

这样的机制能够让使用者快速地绘制数据,而不用换担心后台细节,比如 matplotlib 运行在什么样的平台,底层使用的渲染库是哪一个(GTK、QT、Tk)。所有的细节都隐藏在 matplotlib 内部。pyplot 这个有状态的接口处理创建图表和坐标轴的逻辑,并把它们与配置的后端联系在一起。同时它也为当前图表和坐标轴保存了数据,可以通过该模块的各种指令进行调用。

显式 API

显式 API 实现了所有被隐藏起来的棘手工作,如渲染图形元素、把图像渲染到平台的图形工具上、处理用户输入等。显式 API 使用面更广,也只有通过它才能进一步挖掘 matplotlib 库的潜力,这也是 matplotlib 官方推荐的使用方式。

使用显式 API 能帮助我们进一步了解 matplotlib 的构建。不论是什么形式的绘图,我们程序的输出结果就是一个 Figure 对象。Figure 对象是构成图像的所有其他元素的顶级容器,其他的元素都是它的子元素,统一叫做 Artist 对象。也可以把 Figure 对象当做一块画布,不同的 Artist 对象在其上进行绘制。

Figure对象全解

以上图为例,所有蓝色的元素都是 Artist 对象。这几乎包含了一个绘图的所有要素。从层级上来看,Figure 对象的下一级是 Axes 对象,也就是我们看到的一幅幅子图,一个 Figure 对象可以包含一个或者多个 Axes 对象;一个 Axes 对象除了包含数据形成的 Artist 对象,还包含一个或多个坐标轴,在 matplotlib 中坐标轴本身也是一个对象,称之为 Axis 对象,X 轴是 XAxis 对象,Y 轴是 YAxis 对象,他俩本质上都是 Axis 的子类实例。综上所述 Artist 对象包含 matplotlib 绘图的一切(文本、坐标轴、图形等等)。

小结

现在我们总结一下,如果将 matplotlib 看做一个软件,它由以下三个部分组成:

  1. matplotlib.pylab:这是用户用来创建类似 matplotlib 中图形的一组函数,这就是隐式 API;
  2. matplotlib API:用于创建和管理图形、文本、线条、图表等一组类,可以理解为显式 API(推荐使用);
  3. 后端:后端是绘图的驱动程序,用于将前端的抽象表示转换为一个个文件或者显式设备。

示例

接下来,举一个例子说明一下二者的区别,第一段代码使用 pyplot 的方式进行绘图;第二段使用面向对象这种显式 API 的方式绘制相同的图像。

# 使用pyplot的形式进行绘图  
x = np.linspace(0, 2 * np.pi, 1000)  
y = np.cos(x)  
plt.title("使用pyplot的方式进行绘图", fontsize=15)  
plt.plot(x, y, lw=3, color='orange')

plt.show()

画图结果如下:

pyplot的方式绘图
# 使用面向对象的方法进行绘图  
# 定义Figure对象  
fig = plt.figure()  
# 定义Axes对象  
ax = fig.add_subplot(111)  
# 定义Artist对象  
line_obj = Line2D(x, y, color='paleturquoise', lw=3, ls='--')  
# 添加Artist对象  
ax.add_artist(line_obj)  
ax.set_title("使用面向对象的方法绘图", fontsize=15)  
ax.set_xlim([0, 2 * np.pi])  
ax.set_ylim([-1, 1])  
  
plt.show()

画图结果如下:

面向对象绘图

补充说明

如果你想进行互动和探索编程,最好通过 Python 交互式 shell 使用 matplotib。为此,最有名的很可能就是 IPython pylab 模式了。它在一个强大并且自省的 shell 里提供 matplotlib 的所有特性。shell 具有一些丰富的特性如历史、内联绘图,如果你使用 IPython Notebook 的话还可以分享你的工作。

IPython Notebook 是一个基于 Web 的 IPython shell 界面, 我们可以把上面面的工作分享出去,或转换成 HTML 或 PDF。Matplotlib 图形已经被嵌入并内联在里面,因此它们也可以被保存下来或者分享出去。

往期回顾

  1. 【matplotlib】可视化解决方案——如何正确展示和保存图像
  2. 【matplotlib】可视化解决方案——如何设置字符串的输出字体效果
  3. 【matplotlib】可视化解决方案——如何正确使用颜色映射表
  4. 【matplotlib】可视化解决方案——如何调整轴脊位置
  5. 【matplotlib】可视化解决方案——如何设置坐标系计量方法
  6. 【matplotlib】可视化解决方案——如何正确使用文本注释
  7. 【matplotlib】可视化解决方案——如何调整计量单位和计量方法
  8. 【matplotlib】可视化解决方案——如何实现图形的动画效果
  9. 【matplotlib】可视化解决方案——如何正确使用plot方法
  10. 【matplotlib】可视化解决方案——如何向画布中添加坐标轴

文中难免会出现一些描述不当之处(尽管我已反复检查多次),欢迎在留言区指正,相关的知识点也可进行分享,希望大家都能有所收获!!如果觉得我的文章写得还行,不妨支持一下。你的每一个转发、关注、点赞、评论都是对我最大的支持!

你可能感兴趣的:(【matplotlib】可视化解决方案——如何正确理解pyplot和OO-API)