本系列文章希望能讓有興趣學習資料科學 (Data Science) 及 Python 程式語言的人,透過淺顯易懂及全新不同的方式,由淺入深獲得相關知識。除了筆者其它 Python 及 NumPy 初體驗文章,這一篇同樣帶領大家在進入資訊科學領域前,充分認識如何利用 Matplotlib 函式庫的強大功能,在 Python 中建立靜態、動畫及互動式可視化,以及理解相關的基礎應用。Matplotlib 將會讓你感受到如何讓簡單的事情變得簡單,讓困難的事情成為可能,

目錄

Matplotlib 簡介

在大數據應用的時代,除了將資料分析後的結果具體呈現之外,總希望可以在整個分析過程當中利用資料視覺化來看出一些有趣及重要的洞見 (insight)。尤其在大數據下的機器學習及人工智慧應用更是重要。Matplotlib 是一個 Python 2D 繪圖庫,同時是 Python 當中用來繪圖、圖表呈現及數據表示非常重要的一個綜合函式庫 (Library)。Matplotlib 擁有一個功能強大的開源 (Open Source) 工具包,用於表示及可視覺化數據。創建者John Hunter 深受 MATLAB 程式環境的啟發,所以蘊藏了一些其元素想法。

將數據可視覺化和用數據來講故事,並將分析中獲得的見解有效地傳達給任何受眾,一直是每個資料科學家都需要的基本技能。 對於大多數初學者來說,他們用來接觸數據可視化和講故事的第一個套件自然會選擇是 Matplotlib。由於網路上得到的資料大都較為混亂,本系列文章希望透過對工具包進行結構化介紹後,來嘗試為初學者揭開 Matplotlib 一些神秘的面紗,首先我們先將重點放在 Matplotlib 的架構及基礎知識,並且了解如何利用數據來建立圖形並進而客製化圖形。

(回目錄)

Matplotlib 安裝

Matplotlib 可以利用 CONDA 或 PIP 等套件包管理器來安裝(可參考 Anaconda 3 介紹及安裝教學)。

  • CONDA

如果使用 conda,最好的實作方式是使用虛擬環境,而不是安裝在基礎環境中:

conda create -n MyEnv
conda activate MyEnv

實際安裝的指令:

conda install matplotlib
  • PIP

Matplotlib 也可以使用 pip 安裝,你可以執行下面命令來安裝 Matplotlib:

pip install matplotlib

在使用 pip 時,建議一樣使用虛擬環境。相關虛擬環境的詳細指南及教學可參考下面文章。

  • 檢查是否安裝成功

要驗證 Matplotlib 是否已經成功安裝在您的系統上,可以在命令提示符下(或 Jupyter Notebook/Colab的編輯單元)執行以下命令。如果 Matplotlib 安裝成功,會顯示安裝的 Matplotlib 版本。

import matplotlib
matplotlib.__version__

(回目錄)

Matplotlib 架構

Matplotlib 的架構主要分三個部分,分別是 Backend LayerArtist LayerScripting Layer,每一個 Layer 都有其負責的功能如下:

  • Backend Layer

網路上有許多參考資料都提到 Matplotlib 的 Backend Layer,但初學者往往會對於一些術語及解釋感到困惑,我試著用比較簡單的方式說明。在使用 Matplotlib 來繪圖或製作數據圖表時,由於每個人的開發環境或練習的介面不同,為了要能有效呈現其強大的繪圖功能,就必須有對應支援的 backend 來溝通(例如有些人是利用 Python Shell 來跟 Matplotlib 進行互動),此時你可以輸入下列資料,你將得到此時用的 backend 是 ’TkAgg’ 來幫你完成你所要的功能。

>>> import matplotlib.pyplot as plt 
>>> plt.get_backend() 
‘TkAgg’

如果你是在 Jupyter Notebook (或 Google Colab) 當中使用 inline 的方式來進行互動,那你鍵入下列資料將得到此時的 backend 是 ’nbAgg’ (如下圖)

當然因應不同使用者的環境及需求,所對應的後端 (backend) 也會不一樣,而為了支援這些不一樣的使用情況,Matplotlib 可以定義不同的輸出功能,並且由使用者前端的程式代碼(繪圖代碼),交給後端來完成工作並製作漂亮或複雜的圖形。

  • Artist Layer

Artist Layer 有兩種型式:基元 (primitives)容器 (containers)。基元可以想成是最基礎的元素,主要是要處理我們在畫布上欲繪製的標準圖形對象,例如 Line2D、Rectangle、Text、AxesImage 等等。而容器則是要處理放置它們的位置,例如 Figure、Subplot 和 Axes。所以Artist Layer 可以清楚知道圖形是如何由各子圖組成的,以及物體在給定的軸坐標系 (Axes) 中的相對位置。

  • Scripting Layer

如果我們正在寫一個應用程式而來使用 Matplotlib,我們可能不會關心腳本層 (Scripting Layer),但這一層可以幫助我們簡化及加速與環境的互動,以方便快速建立圖形。前面所提Backend Layer 著重於為工具包提供一個重要的接口,來呈現 Artist Layer 的基元 (primitives)和容器 (containers) ,但 Scripting Layer 卻是以用戶的角度來簡化與其他層一起工作的任務。而在本文章中的範例,所使用的腳本層就做 pyplot。
上述說明了 Matplotlib 就像個多層次的蛋糕一樣。有一個後端層 (Backend Layer) 來處理實際的繪圖,而在他的上面則有一群藝術家層 (Artist Layer) 描述著許多數據的排列方式,再根據腳本層 (Scripting Layer) 實際創建了這些藝術家並將它們一起編排起來表演。相信這樣的說明再配合後面的範例,將可讓初學者更了解其架構。

(回目錄)

繪圖結構及工作流程

  • 繪圖結構剖析 (Plot Anatomy)

我們將一張圖的架構解析如下,其中圖形 (Figure) 包含並管理圖中的許多元素,而主要架構則決定將圖形與行為分開。

  • 工作流程 (Workflow)

用 Matplotlib 創建新圖時,可參考下列基本步驟及範例:
Step 1 :準備資料 (Prepare Data)
Step 2 :建立繪圖 (Create Plot)
Step 3 :繪圖常例 (Plot Routines)
Step 4 :客製化繪圖 (Customize Plot)
Step 5 :儲存圖形 (Save Plot)
Step 6 :圖形展示 (Show Plot)

import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]           # Step 1
y = [5, 10, 20, 35, 45]       # Step 1
fig = plt.figure()            # Step 2
ax = fig.add_subplot(111)     # Step 3
plt.plot(x, y, color='blue', linewidth=2, marker='o') # Step 3&4
plt.xlim(1, 5.5)                   
plt.savefig('workflow.png')   # Step 5
plt.show()                    # Step 6

根據上面步驟範例產生下面圖形。

(回目錄)

Matplotlib 基礎知識與操作

1. 準備資料 (Prepare The Data)

>>> import matplotlib.pyplot as plt # import matplotlib
>>> import numpy as np              # import numpy
>>> x = np.linspace(0, 10, 100)     # x在0到10之間取100個元素
>>> y = np.cos(x)                   # 將產生的x元素,代入cos()產生對應y值
>>> z = np.sin(x)                   # 將產生的x元素,代入sin()產生對應z值
>>> plt.plot(x, y)
[<matplotlib.lines.Line2D object at 0x000002896B067F28>]
>>> plt.show()

(回目錄)

2. 建立繪圖 (Create Plot)

  • Graphs on common axes

範例:

>>> import matplotlib.pyplot as plt
>>> Taipei_HTemp = [16.1, 16.5, 18.5, 21.9, 25.2, 27.7, 29.6, 29.2, 27.4, 24.5, 21.5, 17.9]
>>> Taipei_LTemp = [13.9, 14.2, 15.8, 19.0, 22.3, 24.6, 26.3, 26.1, 24.8, 22.3, 19.3, 15.6]
>>> month = range(1, 13)
>>> plt.plot(month, Taipei_HTemp, 'red')  # 讀出month及Taipei_HTemp的資料,產生紅色線
>>> plt.plot(month, Taipei_LTemp, 'blue') # 讀出month及Taipei_LTemp的資料,產生藍色線
>>> plt.xlabel('Month')                   # x軸的Label
>>> plt.title('Taipei High and Low Temperature') # 此圖的title
>>> plt.show()
  • axes()

語法:axes( [x, y, width, height] )

範例:

>>> import matplotlib.pyplot as plt
>>> Taipei_HTemp = [16.1, 16.5, 18.5, 21.9, 25.2, 27.7, 29.6, 29.2, 27.4, 24.5, 21.5, 17.9]
>>> Taipei_LTemp = [13.9, 14.2, 15.8, 19.0, 22.3, 24.6, 26.3, 26.1, 24.8, 22.3, 19.3, 15.6]
>>> month = range(1, 13)
>>> plt.axes([0.05,0.1,0.425,0.9])
>>> plt.plot(month, Taipei_HTemp, 'red')
>>> plt.xlabel('Month')
>>> plt.title('Taipei High Temperature')
>>> plt.axes([0.525,0.1,0.425,0.9])
>>> plt.plot(month, Taipei_LTemp, 'blue')
>>> plt.xlabel('Month')
>>> plt.title('Taipei Low Temperature')
>>> plt.show()

利用 axes() 的方法可以將資料分成兩張圖的方式呈現,並且可以分開控制其相關參數。雖然看起來左右圖形長得很像,但仔細觀察 y 軸刻度是不一樣的,未來教大家調整成一樣的刻度時就會看出明顯的差異。

  • subplot()

語法:subplot(nrows, ncols, nsubplot)
nrows:列數
ncols:行數
nsubplot:第 n 個子圖
如果 nrows、ncols、nsubplot 數字都在 0~9 之間的話,可以簡寫成如 subplot(321),表示為將子圖分成 3 列 2 行(共 6 個子圖)中的第 1 個。

>>> import matplotlib.pyplot as plt
>>> plt.subplot(321)
>>> plt.subplot(322)
>>> plt.subplot(312)
>>> plt.subplot(337)
>>> plt.subplot(338)
>>> plt.subplot(339)
>>> plt.show()

範例:

>>> import matplotlib.pyplot as plt
>>> Taipei_HTemp = [16.1, 16.5, 18.5, 21.9, 25.2, 27.7, 29.6, 29.2, 27.4, 24.5, 21.5, 17.9]
>>> Taipei_LTemp = [13.9, 14.2, 15.8, 19.0, 22.3, 24.6, 26.3, 26.1, 24.8, 22.3, 19.3, 15.6]
>>> month = range(1, 13)
>>> plt.subplot(2, 1, 1)
>>> plt.plot(month, Taipei_HTemp, 'red')
>>> plt.xlabel('Month')
>>> plt.title('Taipei High Temperature')
>>> plt.subplot(2, 1, 2)
>>> plt.plot(month, Taipei_LTemp, 'blue')
>>> plt.xlabel('Month')
>>> plt.title('Taipei Low Temperature')
>>> plt.tight_layout()
>>> plt.show()

(回目錄)

3. 客製化繪圖 (Customize Plot)

  • Basic Plot
>>> import matplotlib.pyplot as plt
>>> Taipei_temp = [23.2, 23.4, 23.3, 22.7, 23.2, 23.4, 23.5, 23.8, 24, 23.9]
>>> year = range(2008, 2018)
>>> plt.plot(year, Taipei_temp)
>>> plt.show()
  • Colors
>>> import matplotlib.pyplot as plt
>>> Taipei_temp = [23.2, 23.4, 23.3, 22.7, 23.2, 23.4, 23.5, 23.8, 24, 23.9]
>>> year = range(2008, 2018)
>>> plt.plot(year, Taipei_temp, color = 'blue')
>>> plt.show()
  • Markers
>>> import matplotlib.pyplot as plt
>>> Taipei_temp = [23.2, 23.4, 23.3, 22.7, 23.2, 23.4, 23.5, 23.8, 24, 23.9]
>>> year = range(2008, 2018)
>>> plt.plot(year, Taipei_temp, color = 'blue', marker='o')
>>> plt.show()
  • Linestyles
>>> import matplotlib.pyplot as plt
>>> Taipei_temp = [23.2, 23.4, 23.3, 22.7, 23.2, 23.4, 23.5, 23.8, 24, 23.9]
>>> year = range(2008, 2018)
>>> plt.plot(year, Taipei_temp, color = 'blue', marker='o', linestyle = '--')
>>> plt.show()
  • Labels and Title
>>> import matplotlib.pyplot as plt
>>> Taipei_temp = [23.2, 23.4, 23.3, 22.7, 23.2, 23.4, 23.5, 23.8, 24, 23.9]
>>> year = range(2008, 2018)
>>> plt.plot(year, Taipei_temp, color = 'blue', marker='o', linestyle = '--')
>>> plt.xlabel('Year', color = 'red')
>>> plt.ylabel('Temperature', color = 'red')
>>> plt.title('10-year Average Temperature', color = 'red')
>>> plt.show()
  • Multiple data
>>> import matplotlib.pyplot as plt
>>> Taipei_temp = [23.2, 23.4, 23.3, 22.7, 23.2, 23.4, 23.5, 23.8, 24, 23.9]
>>> Taichung_temp = [23.5, 23.8, 23.7, 23.5, 23.6, 23.6, 23.8, 24.3, 24.2, 24.2]
>>> Kaohsiung_temp = [25.1, 25.4, 25.4, 24.9, 25.4, 25.5, 25.6, 26.1, 25.9, 26.3]
>>> year = range(2008, 2018)
>>> plt.plot(year, Taipei_temp, color = 'blue', marker='o', linestyle = '--')
>>> plt.plot(year, Taichung_temp, color = 'orange', marker='o', linestyle = '-')
>>> plt.plot(year, Kaohsiung_temp, color = 'green', marker='.', linestyle = '-.')
>>> plt.xlabel('Year', color = 'red')
>>> plt.ylabel('Temperature', color = 'red')
>>> plt.title('10-year Average Temperature', color = 'red')
>>> plt.show()
  • Legends
>>> import matplotlib.pyplot as plt
>>> Taipei_temp = [23.2, 23.4, 23.3, 22.7, 23.2, 23.4, 23.5, 23.8, 24, 23.9]
>>> Taichung_temp = [23.5, 23.8, 23.7, 23.5, 23.6, 23.6, 23.8, 24.3, 24.2, 24.2]
>>> Kaohsiung_temp = [25.1, 25.4, 25.4, 24.9, 25.4, 25.5, 25.6, 26.1, 25.9, 26.3]
>>> year = range(2008, 2018)
>>> plt.plot(year, Taipei_temp, color = 'blue', marker='o', linestyle = '--', label='Taipei')
>>> plt.plot(year, Taichung_temp, color = 'orange', marker='o', linestyle = '-', label='Taichung')
>>> plt.plot(year, Kaohsiung_temp, color = 'green', marker='.', linestyle = '-', label='Kaohsiung')
>>> plt.legend(loc = 'upper left')
>>> plt.xlabel('Year', color = 'red')
>>> plt.ylabel('Temperature', color = 'red')
>>> plt.title('10-year Average Temperature', color = 'red')
>>> plt.show()
  • Ticks
>>> import matplotlib.pyplot as plt
>>> Taipei_temp = [23.2, 23.4, 23.3, 22.7, 23.2, 23.4, 23.5, 23.8, 24, 23.9]
>>> Taichung_temp = [23.5, 23.8, 23.7, 23.5, 23.6, 23.6, 23.8, 24.3, 24.2, 24.2]
>>> Kaohsiung_temp = [25.1, 25.4, 25.4, 24.9, 25.4, 25.5, 25.6, 26.1, 25.9, 26.3]
>>> year = range(2008, 2018)
>>> plt.plot(year, Taipei_temp, color = 'blue', marker='o', linestyle = '--', label='Taipei')
>>> plt.plot(year, Taichung_temp, color = 'orange', marker='o', linestyle = '-', label='Taichung')
>>> plt.plot(year, Kaohsiung_temp, color = 'green', marker='.', linestyle = '-', label='Kaohsiung')
>>> plt.legend(loc = 'upper left')
>>> plt.xlabel('Year', color = 'red')
>>> plt.ylabel('Temperature', color = 'red')
>>> plt.title('10-year Average Temperature', color = 'red')
>>> plt.xticks([2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017], [97, 98, 99, 100, 101, 102, 103, 104, 105, 106])
>>> plt.show()
  • Limits
>>> import matplotlib.pyplot as plt
>>> Taipei_temp = [23.2, 23.4, 23.3, 22.7, 23.2, 23.4, 23.5, 23.8, 24, 23.9]
>>> Taichung_temp = [23.5, 23.8, 23.7, 23.5, 23.6, 23.6, 23.8, 24.3, 24.2, 24.2]
>>> Kaohsiung_temp = [25.1, 25.4, 25.4, 24.9, 25.4, 25.5, 25.6, 26.1, 25.9, 26.3]
>>> year = range(2008, 2018)
>>> plt.plot(year, Taipei_temp, color = 'blue', marker='o', linestyle = '--', label='Taipei')
>>> plt.plot(year, Taichung_temp, color = 'orange', marker='o', linestyle = '-', label='Taichung')
>>> plt.plot(year, Kaohsiung_temp, color = 'green', marker='.', linestyle = '-', label='Kaohsiung')
>>> plt.xlim(2005, 2018)           # 調整x軸
>>> plt.ylim(20, 35)               # 調整y軸
>>> plt.legend(loc = 'upper left')
>>> plt.xlabel('Year', color = 'red')
>>> plt.ylabel('Temperature', color = 'red')
>>> plt.title('10-year Average Temperature', color = 'red')
>>> plt.xticks([2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017], [97, 98, 99, 100, 101, 102, 103, 104, 105, 106])
>>> plt.show()
  • Annotate
import matplotlib.pyplot as plt
>>> Taipei_temp = [23.2, 23.4, 23.3, 22.7, 23.2, 23.4, 23.5, 23.8, 24, 23.9]
>>> Taichung_temp = [23.5, 23.8, 23.7, 23.5, 23.6, 23.6, 23.8, 24.3, 24.2, 24.2]
>>> Kaohsiung_temp = [25.1, 25.4, 25.4, 24.9, 25.4, 25.5, 25.6, 26.1, 25.9, 26.3]
>>> year = range(2008, 2018)
>>> plt.plot(year, Taipei_temp, color = 'blue', marker='o', linestyle = '--', label='Taipei')
>>> plt.plot(year, Taichung_temp, color = 'orange', marker='o', linestyle = '-', label='Taichung')
>>> plt.plot(year, Kaohsiung_temp, color = 'green', marker='.', linestyle = '-', label='Kaohsiung’)
>>> plt.annotate('Taipei High Tempature', xy=(2016, 24),  xytext=(2015, 23.2), arrowprops={'color':'red'})
>>> plt.annotate('Taichung High Tempature', xy=(2015, 24.3),  xytext=(2014, 24.8), arrowprops={'color':'red'})
>>> plt.annotate('Kaohsiung High Tempature', xy=(2017, 26.3),  xytext=(2015, 25.5), arrowprops={'color':'red'})
>>> plt.legend(loc = 'upper left')
>>> plt.xlabel('Year', color = 'red')
>>> plt.ylabel('Temperature', color = 'red')
>>> plt.title('10-year Average Temperature', color = 'red')
>>> plt.xticks([2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017])
>>> plt.show()

(回目錄)

4. 儲存繪圖 (Save Plot)

可將建立後的圖形存成檔案格式,如下面範例。

  • Save figures
>>> plt.savefig('test1.png')
  • Save transparent figures
>>> plt.savefig('test2.png', transparent=True)

(回目錄)

後續會再分享 Matplotlib 相關文章給有興趣的初學者。

如果你喜歡這篇文章歡迎訂閱、分享(請載名出處)追蹤,並持續關注最新文章。同時 FB 及 IG 也會不定期提供國內外教育與科技新知。

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s