本文很短, 只是為了大家能夠更了解matplotlib的作圖機(jī)制.
適合剛剛?cè)腴T(mén)的朋友們
1. figure和axes
- figure是作圖的畫(huà)布 : matplotlib.figure.Figure
- 你可以在figure上面鋪展axes, 事實(shí)上, 你畫(huà)的圖其實(shí)都是畫(huà)在axes上的 : matplotlib.pyplot.axes
以下展示一下兩者關(guān)系:
plt.figure(facecolor='cyan');
plt.gcf().subplots(2,2);
注: 水藍(lán)色就是figure, 帶數(shù)字框框就是axes
瀏覽兩者的api, 你會(huì)發(fā)現(xiàn), figure的大部分功能, 都是和普通的圖像屬性以及鋪展axes相關(guān)的. 而觀察axes的api, 你會(huì)發(fā)現(xiàn)它是科學(xué)作圖的代理, 有條形圖, 散點(diǎn)圖, 折線圖等等的豐富強(qiáng)大的功能, axes其實(shí)是在一幅畫(huà)布上, 規(guī)劃出的一個(gè)個(gè)科學(xué)作圖的坐標(biāo)軸系統(tǒng)
2. 很多教程中的plt.<某種圖像類型>
做了什么
初學(xué)之時(shí), 我們常常會(huì)用, plt.plot()
, plt.scatter()
, plt.bar()
等等函數(shù)來(lái)畫(huà)圖, 不過(guò)這些函數(shù)的本質(zhì)還是在axes上作圖, 它們做的事情你可以理解為
- 首先得到當(dāng)前活躍的axes, 如果當(dāng)前figure上還沒(méi)有axes, 就幫你創(chuàng)建一個(gè)axes, 然后將它設(shè)為當(dāng)前活躍的axes
- 調(diào)用這個(gè)當(dāng)前axes上的各個(gè)作圖功能.
這里有兩個(gè)重要的函數(shù):
plt.gcf() # 意為, get current figure
plt.gca() # 意為, get current axes
所以, 一些初級(jí)教程教的
plt.<blablabla>
中其實(shí)有不少相當(dāng)于plt.gca().<blablabla>
, 它們很快能夠看到效果, 但是到了我們需要復(fù)雜地鋪展子圖的時(shí)候, 它們就不好用了, 不過(guò)現(xiàn)在理解了axes
其實(shí)是作圖的基本代理之后, 我們就能對(duì)整件事有更多把握了.
3. 在figure上自由地鋪展axes并獲取它們!
首先, 我造一些玩具數(shù)據(jù)
foo = ['a','b','c']
bar = [1,2,3]
第一招:
_, axes = plt.subplots(2,2, figsize=(6, 6)) # 第一個(gè)參數(shù)是創(chuàng)建的figure
axes[0][0].bar(foo, bar);
axes[0][1].scatter(bar, bar);
axes[1][0].plot(bar, bar);
axes[1][1].pie(bar);
plt.subplots(2,2, figsize=(6, 6))
會(huì)創(chuàng)建一個(gè)新的figure, 然后在這個(gè)figure上面鋪展2x2一共4個(gè)axes, 然后返回figure以及axes, 這些axes能夠直接通過(guò)索引獲取, 所以你可以輕易地將它寫(xiě)到循環(huán)中:
_, axes = plt.subplots(2,2, figsize=(6, 6))
colors = ['r', 'g', 'b', 'k']
for ax, c in zip(axes.flatten(), colors):
ax.plot(bar, bar, c=c)
這一招我自己最常用, 子圖可以作為一個(gè)新的維度存在, 用來(lái)組織數(shù)據(jù)中取值范圍比較少的離散維度, 比如禮拜幾這類
第二招
這招就定制化比較高了, 我自己用得比較少, 具體來(lái)說(shuō), 它可以做出這樣的布局
它的代碼如下:
plt.subplot(3,1,1)
plt.subplot(3,3,4)
plt.subplot(3,3,5)
plt.subplot(3,3,6)
plt.subplot(3,1,3)
格式為plt.subplot(<行數(shù)>, <列數(shù)>, <序號(hào)>)
, 以上代碼創(chuàng)建了一個(gè)3x3的布局, 3x3的布局是能夠和3x1的布局耦合的, 只要將3x3的第一行的三個(gè)子圖合成一個(gè)長(zhǎng)條就OK. 對(duì)應(yīng)的代碼就是plt.subplot(3,1,1)
和plt.subplot(3,1,3)
它們都是返回axes的, 所以你可以
ax1 = plt.subplot(3,1,1)
ax1.plot(bar, bar)
不過(guò), 每次調(diào)用完plt.subplot(...)
之后, 新產(chǎn)生的axes會(huì)變成當(dāng)前axes, 因此可以:
plt.subplot(3,1,1)
plt.plot(bar, bar)
plt.subplot(3,3,4)
plt.plot(bar, bar)
...
第三招!
還是一樣, 鋪展axes, 然后獲取這些axes作圖, 這次你可以做出這樣的:
怎么做的呢? 經(jīng)過(guò)上面的作圖原理介紹, 這一次, matplotlib的文檔你應(yīng)該能直接看明白了, 直接傳送:
https://matplotlib.org/users/gridspec.html
4. 為什么我要關(guān)注axes?
axes能夠幫助我們實(shí)現(xiàn)定點(diǎn)作圖, 一些非常受歡迎的庫(kù), 比如pandas和seaborn, 它們大部分的作圖函數(shù)都有一個(gè)叫ax
的參數(shù), 用來(lái)控制圖最終出現(xiàn)在哪個(gè)axes上. 毫不夸張地說(shuō), 我個(gè)人對(duì)于matplotlib的操控感就是從了解了這個(gè)基本的作圖機(jī)制開(kāi)始的??
5. 總結(jié)
如果你
- 明白了matplotlib的作圖機(jī)制
- 明白了鋪展axes并定位到每個(gè)axes進(jìn)行作圖的方法
- 想要回去自己嘗試
就給我個(gè)??吧, 哈哈哈~