作者:luanhz
來源:小數志
Matplotlib入門詳細教程
Matplotlib作為數據科學的的必備庫,算得上是python可視化領域的元老,更是很多高級可視化庫的底層基礎,其重要性不言而喻。
本篇對matplotlib進行系統性介紹,不會面面俱到,但求體系完備、詳略得當。
行文目錄結構,重點是右三分支
matplotlib是python的一個繪圖庫,與numpy、pandas共享數據科學三劍客的美譽,也是很多高級可視化庫的基礎。matplotlib不是python內置庫,調用前需手動安裝,且需依賴numpy庫。截至當前,matplotlib發行版本號為3.2.1,適配python3.6及以上版本。
matplotlib,是matrix + plot + library的縮寫,雖然命名很是直觀,但個人接觸之初卻是常常不禁嗤之以鼻:類比numpy、pandas、sklearn這些簡潔易寫的庫名,matplotlib由三個單詞縮略而成,冗餘得多;尤其是後面加了個lib,好像不加lib就不是庫?matplotlib自身名字長也就罷了,但調用它的時候居然還不能簡單的直接調用,而是要用它的子模塊pyplot。那既然pyplot是核心繪圖模塊,為什麼不把其接口引入到頂層呢?那樣直接import matplotlib就行,而無需每次都import matplotlib.pyplot as plt了雖然pyplot是matplotlib下的子模塊,但二者的調用關係卻不是matplotlib調用pyplot,而是在pyplot中調用matplotlib,略顯本末倒置?當然,我等作為使用者、調包俠,自然是無法領會開發者的獨特考慮,也絕無資格對其評三道四,僅做吐槽一二。pyplot部分調用模塊
前面說到,調用matplotlib庫繪圖一般是用pyplot子模塊,其集成了絕大部分常用方法接口,查看pyplot源碼文件可以發現,它內部調用了matplotlib路徑下的大部分子模塊(不是全部),共同完成各種豐富的繪圖功能。其中有兩個需要重點指出:figure和axes,其中前者為所有繪圖操作定義了頂層類對象Figure,相當於是提供了畫板;而後者則定義了畫板中的每一個繪圖對象Axes,相當於畫板內的各個子圖。換句話說,figure是axes的父容器,而axes是figure的內部元素,而我們常用的各種圖表、圖例、坐標軸等則又是axes的內部元素。
當然,之所以不能稱pyplot為一級命名空間的原因,不僅僅在於它在形式上隸屬於matplotlib,最主要的在於它還不算是matplotlib的「獨裁者」,因為matplotlib的另一個重要模塊——pylab——或許稱得上是真正意義上的集大成者:pylab被定位是python中對MATLAB的替代產品,也就是說凡是MATLAB可以實現的功能,pylab通通都要有,例如矩陣運算(包括常規矩陣運算、線性代數、隨機數、FFT等)、繪圖功能等等。pylab導入的那些重量級模塊
至此,關於matplotlib的pyplot和pylab兩個子模塊,我們可以得出2點結論:pylab集成了numpy和pyplot全部功能
當了解pylab模塊功能之後,才真正理解開發者的深謀遠慮:原以為matplotlib的意思是"面向矩陣的繪圖庫",哪知其真正意義是"矩陣+繪圖庫",繪圖只是它的一半。不過,也正因為pylab模塊集成了過多的功能,直接調用並不是一個明智的選擇,官方已不建議用其繪圖。註:按照慣例,本文後續多以plt作為matplotlib.pyplot別名使用。
用matplotlib繪製可視化圖表,主要有3種接口形式:plt接口和面向對象接口混合繪圖
鑑於pylab的特殊性,matplotlib繪圖主要採用前2種方式。而在二者之間:需要指出,Axes從形式上是坐標軸axis一詞的複數形式,但意義上卻遠非2個或多個坐標軸那麼簡單:如果將Figure比作是畫板的話,那麼Axes就是畫板中的各個子圖,這個子圖提供了真正用於繪圖的空間,除了包含純粹的兩個坐標軸(axes)外,自然還包括圖形、圖例等。所以準確的講,如果說Axes和坐標軸有何關聯的話,那麼Axes應該算是廣義的坐標軸,或簡單稱之為子圖即可。
plt.subplots同時返回figure和axes實例
默認將最後一個axes子圖作為"當前"圖
plot接口文檔及部分參數
當然,各圖表接口參數繁多且不盡一致,全部熟記幾乎不現實,可僅記住常用參數及相關可選項,其他留作使用時查閱即可配置圖例:對所繪圖形進一步添加圖例元素,例如設置標題、坐標軸、文字說明等,常用接口如下:關於圖例配置的官方解釋
plt接口繪圖中配置常用圖例
對此,一方面兩類接口雖然略有區別,但也還算有規律;另一方面,在面向對象繪圖配置圖例時,有更為便捷的設置圖例接口axes.set(),其可以接收多種參數一次性完成所有配置,這也正是面向對象繪圖的強大之處。
前面提到,figure為繪圖創建了畫板,而axes基於當前畫板創建了1個或多個子圖對象。為了創建各種形式的子圖,matplotlib主要支持4種添加子圖的方式。
常用的添加子圖的方法莫過於subplot和subplots兩個接口,其中前者用於一次添加一個子圖,而後者則是創建一組子圖。
除此之外,plt.axes也可通過接收尺寸參數實現多子圖繪製:在添加子圖時傳入一個含有4個數值的元組,分別表示子圖的底坐標和左坐標(設置子圖原點位置)、寬度和高度(設置子圖大小),從而間接實現子圖僅佔據畫板的一塊子區域。相應的方法接口在面向對象接口中是fig.add_axes(),僅僅是接口名字不同,但參數和原理是一致的。例如:應用plt.axes繪製多子圖
通過axes繪製多子圖,應對簡單需求尚可,但面對複雜圖表繪製時難免過於繁瑣:需要手工計算各子圖的原點位置和大小,意味著可能需要多次嘗試。此時,可選的另一種繪製多子圖的接口是plt.GridSpec。實際上,GridSpec只是對subplot接口的一個變形,本質上仍然是執行類似subplot多子圖流程:通過切片將多子圖合併,實現不規則多子圖的繪製。與subplot、axes在面向對象和plt兩類繪圖接口間的區別類似,GridSpec在面向對象時的接口為add_gridspec()。
這裡直接給出官網的一個繪製圖例,具體可查看官方示例代碼:應用plt.GridSpec實現複雜多子圖繪製
實際上,前述在配置圖例過程中,每次繪製都需要進行大量自定義代碼設置(這也是matplotlib的一個短板),在少量繪圖工作時尚可接受,但在大量相似繪圖存在重複操作時,仍然採取這一方法不會是一個明智的選擇(雖然也可以簡單的封裝成一個函數)。
為此,matplotlib提供了自定義參數實現批量配置——rcParams,全稱runtime configuration Parameters,即運行時配置參數。顧名思義,就是在python程序運行時臨時執行的配置參數。rcParams是一個字典格式,當前共有299個鍵值對,分別對應一組參數配置選項。其中用得最多的可能是通過設置字體和減號編碼來解決亂碼的問題,但實際上它的功能強大之處可遠非如此。設置rcParams解決中文亂碼的問題
另一個簡單易用的自定義配置選項是style,即設置繪圖風格,最早在matplotlib1.4版本中引入,當前共支持26種繪圖風格,這裡的繪圖風格類似於很多IDE支持不同主題。可以通過plt.style.available命令查看,返回一個可選風格的列表。例如,以下命令設置繪圖為senborn風格設置seaborn繪圖風格
在可視化愈發重要的當下,matplotlib當然不僅支持簡單的2D圖表繪製,其也提供了對3D繪圖的豐富接口。
contour,實際上是一個偽3D圖形,仍然是在2維空間繪圖,但可以表達3維信息。例如在機器學習中,contour常用於繪製分類算法的超平面如果需要繪製真3D圖形,則需要額外導入matplotlib專用3D繪圖庫:mpl_toolkits,包括3D版的Axes對象和常用圖表的3D版: