大家好,我是早起,這篇文章沒有代碼,只做一件事:嘗試講明白Matplotlib
的工作機(jī)制,先說說我剛開始是怎樣學(xué)習(xí)Matplotlib的吧(可能也是你的)??
大概在幾年前,我還是一個Excel Boy,在學(xué)習(xí)了一段時間Python后,發(fā)現(xiàn)用Matplotlib居然也能制作精美的圖形,于是百度【Matplotlib怎么制作xx圖】,之后隨便點開一兩個網(wǎng)站,跳過大段文字部分,直接復(fù)制代碼粘貼運行,成功得到圖片。OK!Matplotlib我會了!
這樣學(xué)不行嗎?當(dāng)然行!我在之前文章中也說過,不管你是怎么做的,能把圖整出來就行。但是這樣的學(xué)習(xí)方式,并不是非常適合Matplotlib,至少在搞明白它的繪圖機(jī)制之前是不行的。
因為同一張圖,你可能在這篇帖子里面發(fā)現(xiàn)是用plt.xxxx
實現(xiàn),另一個帖子里用ax.xxxx
實現(xiàn),并且有時想修改一個參數(shù),你會百度得到很多種修改方法,但是沒有一個對你有用!因為你甚至都不了解它的工作機(jī)制!
那么接下來,讓我盡可能用通俗易懂的話去解決這個問題!
讓我們從最熟悉、最常見的plt開始,相信你一定執(zhí)行過無數(shù)次下面的代碼
import matplotlib.pyplot as plt
然后就是直接用plt.xxx
去搞各種圖表了,但是你有想過這個**plt到底是什么?**我們把它打印出來看一下??
可以看到,plt
只是一個module
,我們根據(jù)上圖路徑找到對應(yīng)pyplot.py
文件,可以看到,常用的繪圖函數(shù)都被封裝在里面。
所以plt它就是包含了一籃子函數(shù)的API,之所以這么搞,就是為了能像Matlab一樣在命令行繪圖,官方文檔中也是如此解釋??
因此我們直接在命令行執(zhí)行plt.bar([1,2,3],[4,5,6])
直接就出來一幅圖了!
但是等等!畫圖不應(yīng)該先搞一塊畫布/區(qū)域用于作圖嗎?在剛剛的代碼中我沒有告訴它在哪畫,也沒有指定坐標(biāo)軸刻度等信息,為什么直接就畫出來了?
這就涉及到子圖和面向?qū)ο?/strong>的概念了,下面,讓初學(xué)者頭疼的axes
該登場了!
為了搞明白plt.xxxx
和ax.xxxx
之間有什么差異,首先我們來研究下**axes
是什么**!
在大多數(shù)使用ax.xxxx
繪圖的開頭都是這樣的代碼??
fig, ax = plt.subplots()
和剛剛一樣,打印出來看下fig
和ax
是什么??
和上一節(jié)不一樣的是,現(xiàn)在不再是一個接口(plt),而是通過plt接口創(chuàng)建了一個figure對象和一個axes對象!那么這兩個對象是什么呢,讓我們看一張官方的圖
一目了然!
最外層的是Figure,也就是畫布,這是Matplotlib中最高等級的對象,不管繪制什么圖都是需要一個畫布!
在畫布(Figure)里面的是Axes,大家可以理解為作圖的區(qū)域(在上圖中只有一個Axes),接下來就可以通過ax.xxxx
在Axes中進(jìn)行創(chuàng)作,當(dāng)然包括title、Axis、label等各種小組件,以及最重要的圖形!
當(dāng)然創(chuàng)建兩個Axes也行,左邊是行,右邊是列,(2,1)表示兩行一列,兩個axes對象??
只不過這時,就是通過ax[0].xxxx
,ax[1].xxxx
分別去在不同的區(qū)域(Axes)進(jìn)行繪制,具體xxxx
是什么不重要,無非是設(shè)置標(biāo)題、坐標(biāo)軸、數(shù)格式之類的,這些我們會在后續(xù)文章進(jìn)行更新。只需要知道,出現(xiàn)了ax.xxxx
就是在指定區(qū)域繪制!
現(xiàn)在,我們來搞定最后的問題,plt和ax有什么區(qū)別?如何選擇?
先回到第一節(jié)最后的問題
「為什么plt沒有指定畫布和區(qū)域也能作圖?」
因為matplotlib默認(rèn)在最近創(chuàng)建的畫布上繪制,而當(dāng)你沒有指定區(qū)域,告訴它去畫圖,他就會自動去生成一個Axes去繪制,進(jìn)一步?jīng)]有畫布,也會自動去創(chuàng)建一個Figure,也稱為隱式繪制。
這好嗎?看上去挺方便的哈,我們來看下面這種情況,創(chuàng)建一個畫布并有三個Axes
我想在第二個axes上添加一個條形圖怎么辦?條形圖不就是plt.bar
,整!
很遺憾,之前說過plt默認(rèn)在最新的axes上作圖,所以只能畫在第三個axes上,就算你將plt.xxxx
放在ax2 = axes[1]
之后也是不行的!
但如果使用ax.xxxx
話就很方便了!我們只需要指定axes然后在想要的區(qū)域畫圖就行了!
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呢,只能通過一個一個創(chuàng)建子圖,然后將plt.xxxx放在指定的位置
注意觀察代碼片段中plt.xxxx
和ax.xxxx
的位置,plt.xxxx
必須跟在ax2后面才能將條形圖畫在第二個axes中,而ax1.xxxx
則沒有限制!
現(xiàn)在,可以讓我們總結(jié)一下。如果使用plt.xxxx
進(jìn)行繪圖,代碼量會少一點,簡單一點,這也是為什么大多數(shù)教程都在使用這種方式。
但是弊端也很明顯,制作單個圖形時,會自動幫你創(chuàng)建figure和axes。而在出現(xiàn)多個子圖時,使用plt操作起來就顯得有點蠢蠢的,所以這時應(yīng)該使用ax.xxxx
進(jìn)行控制,但是一定要記住使用ax標(biāo)準(zhǔn)的流程:
ax.xxxx
在指定Axes上繪圖那對于這兩種方法,官方怎么說??
上面是翻譯后的官方文檔,可以看到**「為了獲得更多控制,可以完全刪除pyplot級別,從而保留純面向?qū)ο蟮姆椒ā?*也就是盡可能的使用我們說的第二種方法去制作。
我的看法是,其實這兩種方法雖然寫法不太一樣,但是大同小異,比如plt.title()
就等于ax.set_title()
,所以在掌握plt.xxxx和ax.xxxx
背后原理之后,**在可以看懂不同風(fēng)格代碼每一句在干嘛后,**在需要繪圖時,選擇一個最簡單的方法把圖做出來即可!
本文僅從概念上,對plt.xxxx和ax.xxxx
兩種繪圖方式進(jìn)行講解,至于xxxx是什么,我會專門再寫一篇文章為大家整理常用的Matplotlib參數(shù)設(shè)置總結(jié)!