深入淺出 Python 視覺化工具 matplotlib、Seaborn 的基礎與架構全指南與教學
最近在使用 matplotlib 畫一些圖時,常常會遇到如子圖、共用 y 軸等問題,甚至在網路上看到範例使用 axis 和 axe 時,總覺得一頭霧水。而網路上的教學卻僅使用 plt.plot
來繪圖,卻不說明為何要使用這些工具。
因此,我希望這篇文章可以為那些剛入門 matplotlib 的讀者提供一個簡單卻容易理解的基礎觀念。本文會提到下面幾個核心的概念:
- matplotlib 的核心 API 觀念與組成
- Matplotlib 的核心繪圖觀念
- 如何精細控制 Matplotlib 繪圖元件
- Seaborn 是如何和 matplotlib 協作
- The future of plot in Python
非常推薦先從核心的 API 與繪圖觀念開始看起,能夠更瞭解 matplotlib 的設計概念,也能夠在未來使用 matplotlib 時,瞭解不同情況下的適用參數。
一、Matplotlib API 概觀
我相信很多讀者包括我,在一開始接觸到 matplotlib 時一定會遇到 plt.plot
和 ax.plot
到底有什麼差異?為什麼有時候要用 plt.show
有時候不用?
其實在 matplotlib 的 API (Application Programming Interface)共分成兩種型態,一種是我們常見到的 plt.plot
或是 df.plot
的格式,另一種則是 ax.plot
的格式。
plt.plot
|繪圖的懶人包(包括df.plot
),會幫你直接在最近使用的圖表上繪圖,沒有的話就會自動新建一個。ax.plot
|手動建立的 API,提供多項客製化的參數與圖表控制。
以我個人的經驗,我會強烈建議先以 ax.plot
的完整 API 來學習,弄懂背後的完整原理,再來使用簡單的 df.plot
懶人包。
瞭解自己為何而用,才能讓工具發揮最大效益。
那麼,就讓我們來深入瞭解 matplotlib 的概念吧!
二、Matplotlib 的核心繪圖觀念
在繪圖之前,要先搞清楚不同參數代表的意思。
- Figure:可以把他當作畫布,一張畫布上可以有很多的 Axes。
- Axes:就是我們俗稱的「子圖」,每個 Axes 一次只能在一張畫布上。
這時就有人說,不對啊?我之前都用 plt.plot
來繪圖,根本沒有用到 figure 和 axes。plt.plot
其實是一個黑盒子,他幫你把基礎的參數設定好,他就會在最近一張子圖生成圖表(沒有則會創建一張);但這不代表背後就沒有 figure 和 axes 的運作。
Add_subplot: 如何生成 “Figure” and “Axes”?
這裡就來實際操作一次畫布 figure 與子圖 axe 的生成:
此時如果直接以 plt.plot(df)
等指令,會在距離最近的途中建立圖。以上面的例子就會是 axe_3
。那如果要在 axe_1
上面畫圖怎麼做呢?只要用以下兩種簡單的方式,就可以繪在指定的圖上了:
Sub_plots: 如何快速生成大量 plots ?
如果我們這一次要建立好幾個子圖(axes),那我們不就要新增一整排的變數axe_x
?因此衍生的更便利的用法 plt.subplots()
可以使用(和前面的方式差了一個 ”s”),因為 axes 可以直接像二維陣列一樣做索引,也可以一起設定不同子圖間的關連。
這裡也放上子圖(subplots / add_subplot)可以設定的選項以供參考:
nrows
|子圖有幾列,通常都會直接放上數字。ncols
|子圖有幾欄,通常都會直接放上數字。sharex
|所有子圖是否共用一樣的 x 軸,調整xlim
會影響呈現範圍。sharey
|所有子圖是否共用一樣的 x 軸,調整ylim
會影響呈現範圍。
三、如何精細控制 Matplotlib 繪圖元件
當我們已經可以輕鬆掌握 Figure 和 axe 來進行繪製後,接下來可以更細部操作的便是每張圖的細節了。這也是最讓人興奮與實用的各項小技巧,如果在閱讀時對特定的設計方式感興趣,也推薦去官網的 gallary 瀏覽。
在這個章節中,筆者會介紹下面幾個常用的環節:
- matplotlib 細節設定
- 如何控制各種繪圖風格
- 刻度、標籤和圖形
- 註釋與繪製箭頭等形狀
- 儲存圖檔
1. matplotlib 細節設定
matplotlib 本身在繪製時,就有許多的配置方案,可以用來控制各種細節甚至適用於出版的圖片。如果想要直接控制這些設定,可以使用 rc
方法:
如果想要一勞永逸地改掉這些設定呢?一樣可以到 home 目錄下修改:
matplotlib/mpl-data/.matplotlibrc
2. 如何控制各種繪圖風格
到這個階段,真的要來繪製 plot 本身了!我們就先從最常見到的折線圖開始說起。當我們繪製折線圖時,其實本身點與點之間是以線性插值來連接,但如果我想要能夠看到變化率呢?我們變可以更改 drawstyle
:
在設定參數時,多數的繪圖方法都可以接受直接以 axe 作為參數,來更有彈性地繪製子圖。下面變順便列出大部分常用的參數:
label
|圖例用的標籤,如上圖的 “Default”。ax
|指定要拿來畫圖的 axe,若沒有指定則會由最靠近呼叫的 axe 畫起style
|用來傳樣式字串,例如‘b-’
等。alpha
|設定 plot 的透明度kind
|可用area
、bar
、barh
、density
、hist
、kde
、line
、pie
logy
|在 y 軸使用對數呈現,logx
亦同。use_index
|以物件的index
作為刻度標籤,預設為 True。rot
|選轉刻度的標籤,如rot=30
即為選轉 30 度。xticks
|x 軸刻度用的值,可以傳入一個list
來指定,yticks
亦同。xlim
|x 軸的範圍,如 [0,100];ylim
亦同。grid
|顯示軸的格線,預設為False
。
同樣地,如果想要直接以 DataFrame 的黑盒子快速繪圖,也可以參考以下的參數:
subplots
|如傳入整個 df,則可將每欄繪製到不同的子圖中。sharex
|如為True
時,所有的 x 軸、刻度、範圍皆相同;sharey
亦同figsize
|以figsize=(6,4)
指定 figure 大小。title
|字串型態,指定標題。legend
|加入子圖的圖例,預設為True
。sort_columns
|預設為使用既有的欄位排序,可調整排序。
b. Other Plot Usage
- Barplot|以 DataFrame 作為輸入時,會以一列中的多個值來作為圖例標題使用;若在參數中加入
stacked=True
,則會形成疊加長條圖。 - density|密度圖(KDE),呼叫
plot.kde
時會使用混合常態估計法。 - Hist|直方圖,要指定
bins=50
的數量,常用數量為資料量的開根號。
3. 刻度、標籤和圖形
大部分的繪圖都會由 xlim
、xticks
和 xticklabels
、 xlabels
四個方法組成圖面。其中分成以 plt 的介面和原生的 matplotlib 的 API。個別的意義分別為:
xlim
|x 軸的範圍,如 [0,100];ylim
亦同。xticks
|x 軸刻度用的值,可以傳入一個list
來指定,yticks
亦同。xticklabels
|用於設定離散的 x 軸,可以傳入一組 list 來設定。
Pyplot 的設定方式:
會繪製在最後一個子圖或目前使用的子圖上。
- 不帶參數呼叫|會傳回當前的參數之值,例如
plt.xlim()
會傳回範圍。 - 帶著參數呼叫|會設定新的值,如
plt.xlim([0, 100])
會設定新範圍。
原生 API 的設定方式:
會直接繪製在指定的子圖上,主要分成 get_
和 set_
兩種設定方法。
axe.get_xlabel()
|便會傳回當下 x 軸的軸名稱。axe.set_xlabel()
|便會設定當下 x 軸的軸名稱。
設定方法亦可以加入 rotation=30
和 fontsize=’small’
等參數如 set_xlabel(ratation=10)
,來進一步設定子圖的刻度與標籤。與上面的例子相同,我們也可以一次用 arg 的方式傳入所有的變數。
有了客製化的標籤,就要加入圖例讀者才容易瞭解不同的線代表哪筆資料。加入的方法主要有兩種:
axe.plot(label=’label_1’)
axe.legend(labels=[‘label_1’, ‘label_2’])
接著如果使用第一種,則要記得呼叫 plt.legend()
或 axe.legend()
。另外如果要設定圖例的位置,可以簡單地使用 loc='best'
,會幫你找不會蓋到圖表的地方呈現,抑或直接指定位置。
4. 註釋與繪製箭頭等形狀
除了圖例之外,有時也會需要繪製一些文字(text)、箭頭(arrow)或註釋(annotate)等,這時就可以使用下面三個方法:
axe.text
|在子圖的指定座標加上文字axe.arrow
|在子圖的指定座標加上箭頭axe.annotate
|註釋可以直接劃上文字和箭頭。
a. axe.text/axe.arrow
可以簡單如以下方式呈現:
b. axe.annotate 則可設定複雜的方法來呈現:
5. 儲存圖檔
當我們繪製好圖表後,有時最後一階段便需要輸出圖檔,這時便可簡單使用 savefig
來儲存當前的 figure。舉例來說,如果想要把圖存成 png:
plt.savefig('savefig.png')
程式會根據你附上的附檔名進行判別,自動生成該類型的檔案。主要儲存的方式一樣分成兩種,一種是 pyplot 如 df.plot 的 API;另一種則是 matplotlib 的原生 API:
plt.savefig
|會儲存當前的 figure。fig.savefig
|會儲存 figure 實例化後fig
畫布上的圖。
在輸出檔案時,有下列參數能夠更細部地調整輸出的圖,舉例來說:
fname
|檔案名稱與位置路徑,以附檔名為檔案型態判斷依據。dpi
|圖片每英吋的解析度,預設為 100dpi。facecolor
|子圖外的背景顏色,預設為‘w’(白色)
。edgecolor
|子圖外的邊框顏色,預設為‘w’(白色)
。format
|明確指定要用的檔案格式。bbox_inches
|指定圖存檔部分,若指定為tight
則會將周圍空白去掉
以上就是我們從建立 figure 畫布、axe 子圖一路到輸出圖表的過程,相信讀者也已經對於如何製作與調整一張圖表,有了比較明確的概念。接著,我們就來講 matplotlib 的高階 API –––– Seaborn。
五、How does Seaborn work?
如果讀者曾經聽過深度學習的框架,那 matplotlib 和 Seaborn 的關係就和 Tenserflow 與 Keras、Pytorch 與 Fast.ai 的關係一模一樣。
Seaborn 背後的底層工具都仍然屬於 matplotlib,但透過封裝的方式大幅度地簡化許多設定上的細節,且也美化的圖表本身的輸出。因此就算只是 import seaborn
本身,也能夠提升 matplotlib 的繪圖視覺美感。
沒事多用 seaborn,圖表看起來就會更漂亮:
import seaborn as sns
為了讓讀者感受一下差異,我們下面就實作幾個圖表來示範。本文會帶到下面五個常用的顯示方式:
- 使用 Seaborn 調整 Theme
- Barplot 直方圖
- Displot 分布密度圖
- Regplot 分布密度圖
- Pairplot 散佈圖矩陣
- Facetgrid 層面圖與分組
1. 使用 Seaborn 調整 Theme
可以看到從 seaborn 輸出的圖明顯多了外框,整體視覺也比較好看。因此筆者在後來在進行 EDA 時,若圖需要輸出都會習慣使用 seaborn 來美化圖。
若要在一開始就調整 seaborn 的風格,可以簡單地使用 set 來調整:
sns.set(style="white") # darkgrid, whitegrid, dark, white, ticks
2. Barplot 直方圖
3. Displot 分布密度圖
使用 seaborn 的 displot 時,會同時呈現直方圖和密度圖,可以更好地去評估分布的組成。
4. Regplot 分布密度圖
Seaborn 的 regplot 可同時繪製出散佈圖(scatter)和回歸(Regression),可以很快速地評估該資料是否有某種趨勢。
5. Pairplot 散佈圖矩陣
在探索資料時,若能看到不同變數間的散佈圖非常有幫助,但如果一個一個繪製不僅容易忘記,也很難直接看到不同變數間的關係。這時 pairplot 就派上用場了。
sns.pairplot(penguins, hue="species", diag_kind="hist")
也許你已經看到函式裡有 diag_kind
的參數,這個參數能讓我們調整離散的資料會以 hist
或 kde
等方式呈現。更詳細的設定內容請察看官網。
6. Facetgrid 層面圖與分組
我們可以使用 facetgrid 來依照多個分類進行視覺化。
axe = sns.FacetGrid(tips, col="time", row="sex")
axe.map(sns.scatterplot, "total_bill", "tip")
更細節的操作可以直接參考官方文件,但官方文件也提到若在使用 FacetGrid 時,仍然盡可能地轉換資料到正確的型態,如類別資料轉換成 category;數值資料則轉換成 int 或 float。
同樣地如果要讓 figure 空白變少,可以使用 tight_layout()
來縮減空白。
fig.tight_layout()
六、The future of plot in Python
隨著資料視覺化的發展,越來越多的人發現靜態的圖表仍然很難呈現所需的所有資料,因此便開始出現了互動圖表,其中在 Python 的領域最有名的新工具便是 Plotly,打著簡單好用的方式便能生成出互動圖表。
互動圖表特別適合應用在 Data-wharehose 的資料視覺化工具,就像 Tableau 的 Dashboard 一樣能夠即時檢視與操作,特別推薦有興趣與需求的讀者,可以來上面的官方網站瀏覽看看喔!
Summary
過去在使用 matplotlib 時,總是必須要東找西找才能找到自己需要的圖表,也常常不確定 axe.plot 和 df.plot 的差異在哪裡,始終囫圇吞棗的用。今天終於把這篇文章整理完了,也算是把之前欠的資料視覺化的債還了一些。
在學習的過程中,推薦讀者也能跟著文中的案例實際操作,並多結合現在工作上、學習上的實際例子進行視覺化的練習,最終學會從資料中判別洞見才是最重要的環節。希望這篇文章能夠對讀者有幫助。
**【希望用你的掌聲來投票與支持】**
拍 5~10 下:簽個到,表示支持(感謝你的鼓勵啊啊啊)
拍 10~30 下:希望我可以多寫一些文章!有你這位讀者,寫這篇也心滿意足了!
拍 30~50 下:內容對你感覺很有共鳴,希望能多分享給周圍的朋友!
謝謝你/妳,願意把我的文章閱讀完
如果你喜歡筆者在 Medium 的文章,可以拍個手(Claps),
也歡迎你分享給你覺得有需要的朋友們。
You May Interest In:
- 深入淺出 SQL 的子查詢 Subquery 各項常用技巧
- 如何快速上手資料科學專案流程(上)A Step-by-Step Guide For A Data Science Project. I
- 快速上手資料科學專案流程全攻略(下)A Step-by-Step Guide For A Data Science Project. II
- 機器學習專案|Kaggle — Airbnb New User Prediction(Top 24%)
- 深入淺出常用推薦系統演算法 Recommendation System
- Statistical Thinking in Python|ECDF 進行 EDA 探索式分析的好工具
- Analyzing Police Activity with pandas 案例實作(一)– 如何高效進行數據分析
- Analyzing Police Activity with pandas 案例實作(二)– 數據整理
- 你可能不知道的 SQL 小筆記(查詢篇)
- [數據分析] Lean Analytics — 總說數據分析,你在分析什麼?
- [Statistic] Hypothesis Testing — 以 Python 實踐假設檢定(附程式碼)
- [DataCamp] 快速解析 Python 的各種Import Data 基礎應用技巧
- [DataCamp] Cleaning Data in Python 如何簡單上手資料清洗