人人都能看懂的 Matplotlib 绘图原理

技术讨论 Cynthia-yawain ⋅ 于 1个月前 ⋅ 148 阅读

作者丨刘早起@知乎(已授权)
来源丨可视化图鉴
编辑丨极市平台

前言

大家好,我是早起,这篇文章没有代码,只做一件事:尝试讲明白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.xxxxax.xxxx之间有什么差异,首先我们来研究下**axes是什么**!

在大多数使用ax.xxxx绘图的开头都是这样的代码

fig, ax = plt.subplots()

和刚刚一样,打印出来看下figax是什么

和上一节不一样的是,现在不再是一个接口(plt),而是通过plt接口创建了一个figure对象和一个axes对象!那么这两个对象是什么呢,让我们看一张官方的图

一目了然!

最外层的是Figure,也就是画布,这是Matplotlib中最高等级的对象不管绘制什么图都是需要一个画布!

在画布(Figure)里面的是Axes,大家可以理解为作图的区域(在上图中只有一个Axes), 接下来就可以通过ax.xxxx在Axes中进行创作,当然包括title、Axis、label等各种小组件,以及最重要的图形!

当然创建两个Axes也行,左边是行,右边是列,(2,1)表示两行一列,两个axes对象

只不过这时,就是通过ax[0].xxxxax[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.xxxxax.xxxx的位置plt.xxxx必须跟在ax2后面才能将条形图画在第二个axes中,而ax1.xxxx则没有限制!

小结

现在,可以让我们总结一下。如果使用plt.xxxx进行绘图,代码量会少一点,简单一点,这也是为什么大多数教程都在使用这种方式。

但是弊端也很明显,制作单个图形时,会自动帮你创建figure和axes。而在出现多个子图时,使用plt操作起来就显得有点蠢蠢的,所以这时应该使用ax.xxxx进行控制,但是一定要记住使用ax标准的流程

  1. 创建一个画布(Figure)
  2. 创建一个或者多个Axes
  3. 使用ax.xxxx在指定Axes上绘图

那对于这两种方法,官方怎么说

上面是翻译后的官方文档,可以看到 「为了获得更多控制,可以完全删除pyplot级别,从而保留纯面向对象的方法」 也就是尽可能的使用我们说的第二种方法去制作。

我的看法是,其实这两种方法虽然写法不太一样,但是大同小异,比如plt.title()就等于ax.set_title(),所以在掌握plt.xxxx和ax.xxxx背后原理之后,**在可以看懂不同风格代码每一句在干嘛后,**在需要绘图时,选择一个最简单的方法把图做出来即可

本文仅从概念上,对plt.xxxx和ax.xxxx两种绘图方式进行讲解,至于xxxx是什么,我会专门再写一篇文章为大家整理常用的Matplotlib参数设置总结!

成为第一个点赞的人吧 :bowtie:
回复数量: 0
暂无回复~
您需要登陆以后才能留下评论!