Matplotlib 有兩種主要的應用程式接口,或者說叫使用風格:
- 一種是顯式調用“Axes”接口,使用Figure或Axes對象的方法來建立Artists,并一步步建立符合你要求的圖象。這種也叫面向對象程式設計風格。
- 一咱是隐式調用“pyplot”接口,它用于跟蹤最新建立的Figure和Axes,并自動添加它認為使用者需要的Artists。 另外,一些下遊的庫,比如pandas和array等,在它們自身的資料集中整合了提供了一個 plot 方法,使用者可以直接調用data.plot()。 這兩種風格的接口讓人看起來有些迷糊,特别是在網絡上有些例子一會兒用這個,一會兒用這個,實作的效果還都差不多。是以這裡我們試着指出“bylot”和它的下遊接口是如保與顯式的“Axes”接口相關聯的。
本地的Matplotlib接口
顯式“Axes”接口
- Axes接口是Matplotlib的基礎實作方式,很多自定義繪圖和微調動作都是這個級别上進行的。 這個接口使用subplots方法執行個體化了一個Figure對象(如下面的fig)并以此來建立一個或多個Axes對象(如下面的ax),然後使用Axes對象的繪圖指令(plot函數)來顯示圖像。 如:
import matplotlib.pyplot as plt
fig = plt.figure() #建立畫布
ax = fig.subplots() # 建立坐标系
ax.plot([1,2,3,4],[4,3,2,1]) #繪圖
[<matplotlib.lines.Line2D at 0xffff812214a8>]
我們叫它“顯式”是因為每個對象都是被顯式調用的。并且用于生成下一個對象。保留對對象的引用可以保持一定的靈活性,并且允許我們在生成對象之後,顯示對象之前對對象進行自定義。
隐式的“pyplot”接口
pylot子產品隐藏了大多數的Axes繪圖方式,但給出了與上個例子等效的圖形,裡面的Figure 和Axes由子產品自動處理了。
import matplotlib.pyplot as plt
plt.plot([1,2,3,4],[4,3,2,1])
[<matplotlib.lines.Line2D at 0xffff811a6cf8>]
這種方式很友善,特别是在進行互動式工作或編簡單的腳本的時候。目前的Figure可以用gcf()函數來進行記錄,目前的Axes用gca()來記錄。pyplot子產品給使用者保留一個Figures的清單,每個Figure保留了一個Axes的清單:
import matplotlib.pyplot as plt
plt.subplot(1,2,1)
plt.plot([1,2,3],[0,5,2])
plt.subplot(1,2,2)
plt.plot([3,2,1],[0,5,2])
[<matplotlib.lines.Line2D at 0xffff8112ca90>]
這相當于
import matplotlib.pyplot as plt
plt.subplot(1,2,1)
ax = plt.gca()
ax.plot([1,2,3],[0,5,2])
plt.subplot(1,2,2)
ax = plt.gca()
ax.plot([3,2,1],[0,5,2])
[<matplotlib.lines.Line2D at 0xffff810497b8>]
如果用顯式接口,它是這樣的。
import matplotlib.pyplot as plt
fig,axs = plt.subplots(1,2)
axs[0].plot([1,2,3],[0,5,2])
axs[1].plot([3,2,1],[0,5,2])
[<matplotlib.lines.Line2D at 0xffff80f0a438>]
為什麼用顯式調用? 當你碰到不得不對沒有使用plt.gca()進行标記的舊軸上進行操作時,會發生什麼?一種簡單的方法是再次用相同的參數調用subplot,但這樣很快就會讓代碼變得臃腫,不夠優雅;另一種是檢查Figure對象的Axes對象清單,但這樣經常會出錯,因為很多其他的色帶也是Axes對象,最好的解決方案也許是給每一個Axes填加一個句柄(一個變量名),但這樣搞的話,就又不如在開始的時候就建立所有的Axes對象來得友善了。來一個例子看看:
import matplotlib.pyplot as plt
plt.subplot(1,2,1)
plt.plot([1,2,3],[0,5,2])
plt.subplot(1,2,2)
plt.plot([3,2,1],[0,5,2])
plt.suptitle('Implicit interface:re-call subplot')
for i in range(1,3):
plt.subplot(1,2,i)
plt.xlabel('Boo')
import matplotlib.pyplot as plt
axs = []
ax1 = plt.subplot(1,2,1)
# axs += [ax1]
axs.append(ax1)
plt.plot([1,2,3],[0,5,2])
ax2 = plt.subplot(1,2,2)
# axs += [ax2]
axs.append(ax2)
plt.plot([3,2,1],[0,5,2])
plt.suptitle('Implicit Interface: save handles')
for i in range(2):
plt.sca(axs[i])
plt.xlabel('Boo')
print(axs)
[<AxesSubplot:xlabel='Boo'>, <AxesSubplot:xlabel='Boo'>]
建議的方式是在開始時就顯式聲明
import matplotlib.pyplot as plt
fig,axs = plt.subplots(1,2)
axs[0].plot([1,2,3],[0,5,2])
axs[1].plot([3,2,1],[0,5,2])
fig.suptitle('Explicit Interface')
for i in range(2):
axs[i].set_xlabel('Boo')
第三方庫的資料對象接口
一些第三方庫已經實作對其資料進行繪圖,比如pandas和array都實作了data.plot()方法,下遊庫可以實作一個簡單的資料容器,該容器将x和y資料存儲在一起,然後實作繪圖方法:
import matplotlib.pyplot as plt
class DataContainer:
def __init__(self,x,y) :
self._x = x
self._y = y
def plot(self,ax = None,**kwargs):
if ax is None:
ax = plt.gca()
ax.plot(self._x,self._y,**kwargs)
ax.set_title('Plotted from DataClass!')
return ax
data = DataContainer([0,1,2,3],[0,2,5,3])
data.plot()
<AxesSubplot:title={'center':'Plotted from DataClass!'}>
是以,第三方庫可以向使用者隐藏所有的細節,并可以根據資料類型進行可視化,并且通常具有良好的标簽、顔色圖選擇和其他友善的功能。
然而,在上述内容中,我們可能不喜歡庫提供的标題。幸運的是,它們從plot()方法中傳回了Axes對象,并且定義了明确的Axes接口,我們可以調用:ax.set_title(“My title”)來定制标題。
許多庫還允許其plot方法接受可選的ax參數。這允許我們在Axes中放置可視化對象并做一些自定義的設定。
總結一下
總的來說,明确了解的“Axes”接口非常有用,因為它是最靈活的對象,并且是其他接口的基礎。使用者通常可以知道如何下拉到顯式接口并對底層對象進行操作。雖然顯式接口的設定可能會更加冗長,但複雜的繪圖通常會比嘗試使用隐式“pyplot”接口更簡單。
類似地,合作夥伴的第三方庫提供的聲明性接口使用“Axes”接口可通路的對象,并經常将這些對象作為參數接受或從方法中傳遞回來。通常需要使用顯式的“Axes”接口來執行預設可視化的自定義設定,或者将資料解壓縮到NumPy數組中并直接傳遞到Matplotlib。
附錄:帶資料結構的“Axes”接口
大多數的Axes方法允許另一種API 即通過将資料對象通過字元串的方式傳遞進去。如
import matplotlib.pyplot as plt
data = {'xdat':[0,1,2,3],'ydat':[3,2,1,0]}
fig,ax = plt.subplots(figsize=(2,2))
ax.plot('xdat','ydat',data=data)
[<matplotlib.lines.Line2D at 0xffff806f6358>]
附錄:“palabra”接口
還有一個接口非常不受歡迎,那就是通過matplotlib.pyplot import*來實作。這允許使用者簡單地調用plot(x,y)。雖然友善,但如果使用者無意中将變量命名為與pyplot方法相同的名稱,這可能會導緻明顯的問題。