人人都能看懂的Matplotlib绘图原理
极市导读
本文从概念上,对plt.xxxx和ax.xxxx两种绘图方式进行讲解,详细阐述两种方式的特点以及不同之处。 >>加入极市CV技术交流群,走在计算机视觉的最前沿
前言
大家好,我是早起,这篇文章没有代码,只做一件事:尝试讲明白Matplotlib
的工作机制,先说说我刚开始是怎样学习Matplotlib的吧(可能也是你的)
大概在几年前,我还是一个Excel Boy,在学习了一段时间Python后,发现用Matplotlib居然也能制作精美的图形,于是百度【Matplotlib怎么制作xx图】,之后随便点开一两个网站,跳过大段文字部分,直接复制代码粘贴运行,成功得到图片。OK!Matplotlib我会了!
这样学不行吗?当然行! 我在之前文章中也说过,不管你是怎么做的,能把图整出来就行。但是这样的学习方式,并不是非常适合Matplotlib,至少在搞明白它的绘图机制之前是不行的。
因为同一张图,你可能在这篇帖子里面发现是用plt.xxxx
实现,另一个帖子里用ax.xxxx
实现,并且有时想修改一个参数,你会百度得到很多种修改方法,但是没有一个对你有用!因为你甚至都不了解它的工作机制!
那么接下来,让我尽可能用通俗易懂的话去解决这个问题!
plt.xxxx到底是什么?
让我们从最熟悉、最常见的plt开始,相信你一定执行过无数次下面的代码
import matplotlib.pyplot as plt
然后就是直接用
plt.xxx
去搞各种图表了,但是你有想过这个plt到底是什么?我们把它打印出来看一下
可以看到,plt
只是一个module
,我们根据上图路径找到对应pyplot.py
文件,可以看到,常用的绘图函数都被封装在里面。
所以plt它就是包含了一篮子函数的API,之所以这么搞,就是为了能像Matlab一样在命令行绘图,官方文档中也是如此解释
因此我们直接在命令行执行plt.bar([1,2,3],[4,5,6])
直接就出来一幅图了!
但是等等!画图不应该先搞一块画布/区域用于作图吗?在刚刚的代码中我没有告诉它在哪画,也没有指定坐标轴刻度等信息,为什么直接就画出来了?
这就涉及到子图和面向对象的概念了,下面,让初学者头疼的axes
该登场了!
ax.xxxx又是什么?
为了搞明白plt.xxxx
和ax.xxxx
之间有什么差异,首先我们来研究下axes
是什么!
在大多数使用ax.xxxx
绘图的开头都是这样的代码
fig, ax = plt.subplots()
和刚刚一样,打印出来看下fig
和ax
是什么
和上一节不一样的是,现在不再是一个接口(plt),而是通过plt接口创建了一个figure对象和一个axes对象!那么这两个对象是什么呢,让我们看一张官方的图
一目了然!
最外层的是Figure,也就是画布,这是Matplotlib中最高等级的对象,不管绘制什么图都是需要一个画布!
在画布(Figure)里面的是Axes,大家可以理解为作图的区域(在上图中只有一个Axes), 接下来就可以通过ax.xxxx
在Axes中进行创作,当然包括title、Axis、label等各种小组件,以及最重要的图形!
当然创建两个Axes也行,左边是行,右边是列,(2,1)表示两行一列,两个axes对象
只不过这时,就是通过ax[0].xxxx
,ax[1].xxxx
分别去在不同的区域(Axes)进行绘制,具体xxxx
是什么不重要,无非是设置标题、坐标轴、数格式之类的,这些我们会在后续文章进行更新。只需要知道,出现了ax.xxxx
就是在指定区域绘制!
plt和ax有什么区别?
现在,我们来搞定最后的问题,plt和ax有什么区别?如何选择?
先回到第一节最后的问题
「为什么plt没有指定画布和区域也能作图?」
因为matplotlib默认在最近创建的画布上绘制,而当你没有指定区域,告诉它去画图,他就会自动去生成一个Axes去绘制,进一步没有画布,也会自动去创建一个Figure,也称为隐式绘制。
这好吗?看上去挺方便的哈,我们来看下面这种情况,创建一个画布并有三个Axes
我想在第二个axes上添加一个条形图怎么办?条形图不就是plt.bar
,整!
很遗憾,之前说过plt默认在最新的axes上作图,所以只能画在第三个axes上,就算你将plt.xxxx
放在ax2 = axes[1]
之后也是不行的!
但如果使用ax.xxxx
话就很方便了!我们只需要指定axes然后在想要的区域画图就行了!
fig, axes = plt.subplots(1,3,figsize=(16,6))
ax1 = axes[0]
ax2 = axes[1]
ax3 = axes[2]
ax2.barh([1,2,3,4,5],[1,2,3,4,5])
plt.show()
那么一定要用plt呢,只能通过一个一个创建子图,然后将plt.xxxx放在指定的位置
注意观察代码片段中plt.xxxx
和ax.xxxx
的位置,plt.xxxx
必须跟在ax2后面才能将条形图画在第二个axes中,而ax1.xxxx
则没有限制!
小结
现在,可以让我们总结一下。如果使用plt.xxxx
进行绘图,代码量会少一点,简单一点,这也是为什么大多数教程都在使用这种方式。
但是弊端也很明显,制作单个图形时,会自动帮你创建figure和axes。而在出现多个子图时,使用plt操作起来就显得有点蠢蠢的,所以这时应该使用ax.xxxx
进行控制,但是一定要记住使用ax标准的流程:
创建一个画布(Figure) 创建一个或者多个Axes 使用 ax.xxxx
在指定Axes上绘图
那对于这两种方法,官方怎么说
上面是翻译后的官方文档,可以看到 「为了获得更多控制,可以完全删除pyplot级别,从而保留纯面向对象的方法」 也就是尽可能的使用我们说的第二种方法去制作。
我的看法是,其实这两种方法虽然写法不太一样,但是大同小异,比如plt.title()
就等于ax.set_title()
,所以在掌握plt.xxxx和ax.xxxx
背后原理之后,在可以看懂不同风格代码每一句在干嘛后,在需要绘图时,选择一个最简单的方法把图做出来即可!
本文仅从概念上,对plt.xxxx和ax.xxxx
两种绘图方式进行讲解,至于xxxx是什么,我会专门再写一篇文章为大家整理常用的Matplotlib参数设置总结!
推荐阅读