July 26, 2018

Matplotlib中的两种绘图API说明

Matplotlib中的两种绘图API说明

在Matplotlib库中提供了两种风格的API供开发者使用:一种是Pyplot编程接口(state-based),一种是面向对象对象的编程接口(object-based)。

Pyplot封装了底层的绘图函数提供了一种绘图环境,使得我们可以直接像在MATLAB那样绘制图形。当我们使用import matplotlib.pyplot as plt语句导入pyplot模块,并使用plt.plot()绘制图形的时候,默认的Figure以及Axes等对象会自动创建以支持图形的绘制。Pyplot一来使得对MATLAB绘图熟悉的童鞋更加容易上手,二来屏蔽了一些底层通用的绘图对象的创建细节,使用更加简洁。

在使用面向对象的编程接口时候,我们需要自己创建画布(FigureCanvas),自己创建图对象(Figure),自己创建Axes(一个Figure可以包含一个或者多个Axes,一个Axes可以理解为一个子图,使用一次plot()绘图函数便会创建一个Axes),所有对象一起才能完成一次完整的绘图。使用面向对象编程接口有利于我们对于图形绘制的完整控制,但是相对于Pyplot接口可能需要书写更多的代码。

在Matplotlib官方文档中,虽然说推荐大家使用面向对象接口进行绘图,但是其中提供的例子大部分都是基于Pyplot接口的。下面我们以一个简单例子(绘制一条直线)体验一下使用两种编程接口编程的异同。

PyPlot接口

import matplotlib.pyplot as plt
plt.plot([1,2,3,4])
plt.title('Title')
plt.grid(True)
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.show()

输出结果如下:

Matplotlib绘制直线

面向对象接口

from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure

fig = Figure()
FigureCanvas(fig)
ax = fig.add_subplot(111)  # add_subplot()方法中的111表示的是1×1格网,第1个子图
ax.plot([1, 2, 3, 4])
ax.set_title('Title')
ax.grid(True)
ax.set_xlabel('X Axis')
ax.set_ylabel('Y Axis')
fig.savefig('test.png', dpi=120)

同样的例子,我们使用面向对象接口用了更多代码,但是其绘制过程也更加明了。另外,提一点,使用面向对象接口不能使用交互式的show()方法对图像直接进行显示。

面向对象的接口需要我们对绘图的backends也有所了解,提供对应的FigureCanvas,这是很不方便的,不利于代码的跨平台移植。所以,我在编程过程中,进程使用两个接口折中的一种方案:

import matplotlib.pyplot as plt

ax = plt.subplot(111)
ax.plot([1, 2, 3, 4])
ax.set_title('Title')
ax.grid(True)
ax.set_xlabel('X Axis')
ax.set_ylabel('Y Axis')
plt.show()

我推荐大家平时也多多使用这种方案,自己创建Axes对象,然后使用面向对象接口做图形绘制。