iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 27
0
Software Development

從零開始學Python系列 第 27

[Day 27] 從零開始學Python - 科學繪圖Matplotlib:畫著你,畫不出你的骨骼

註:本文同步刊載在Medium,若習慣Medium的話亦可去那邊看呦!

今天我們要來介紹的是Matplotlib,
對於Python來說,是一套非常常用於科學繪圖的繪圖程式庫,
同時也相當良好地支援了NumPy的陣列,
此外,通常狀況下,只要設定恰當,
也可以很順利地在一些帶有視窗運作的Python執行環境,
如IPython, Jupyter Notebook, colab等直接內嵌繪製圖片,
可以說是相當的方便!
由於最初的目的是提供如同Matlab軟體的繪圖方式,
所以常用Matlab的人可能會覺得很多東西似曾相識XD

要使用matplotlib時,官方有提供pylab
將matplotlib的pyplot和numpy合併在一起,
但還是建議numpy歸numpy,pyplot歸pyplot

同樣的,如果電腦還沒有matplotlib套件的話,
請先使用pip install進行安裝。

pip install matplotlib

接下來讓我們來介紹一些基本的功能。
首先,我們要先將numpy和matplotlib的pyplot給import進來:

import numpy as np
import matplotlib.pyplot as plt

記得上一篇我們做過一個隨積分布的陣列嗎?
如果我們想將其使用直方圖(Histogram)來表現出點的分布數量的話,
可以使用plt.hist(),將陣列輸入給plt;
同時,plt在繪製以後,要經過plt.show()的方法才會顯示出來。

>>> mu, sigma = 0, 0.1
>>> s = np.random.normal(mu, sigma, 1000)
>>> plt.hist(s) # 繪製直方圖,預設分成10組
(array([ 10.,  32.,  91., 164., 238., 216., 147.,  71.,  25.,   6.]), array([-0.
30285466, -0.2403016 , -0.17774855, -0.1151955 , -0.05264245,
        0.0099106 ,  0.07246365,  0.1350167 ,  0.19756975,  0.2601228 ,
        0.32267585]), <BarContainer object of 10 artists>)
>>> plt.show()
# 在直譯器的話可以按Ctrl+C回來或按X關掉plt視窗
>>> plt.hist(s, 30) # 第二個參數為30, 代表將值的範圍切分成30等份(預設則為10)
(array([ 1.,  4.,  5.,  8.,  9., 15., 19., 25., 47., 46., 49., 69., 71.,
       79., 88., 87., 76., 53., 55., 55., 37., 40., 16., 15.,  9.,  9.,
        7.,  4.,  1.,  1.]), array([-0.30285466, -0.28200364, -0.26115262, -0.24
03016 , -0.21945059,
       -0.19859957, -0.17774855, -0.15689754, -0.13604652, -0.1151955 ,
       -0.09434449, -0.07349347, -0.05264245, -0.03179144, -0.01094042,
        0.0099106 ,  0.03076161,  0.05161263,  0.07246365,  0.09331467,
        0.11416568,  0.1350167 ,  0.15586772,  0.17671873,  0.19756975,
        0.21842077,  0.23927178,  0.2601228 ,  0.28097382,  0.30182483,
        0.32267585]), <BarContainer object of 30 artists>)
>>> plt.show()

應該可以看到接近如下的圖(前面是分10組,後面是分30組):
https://ithelp.ithome.com.tw/upload/images/20201006/201198719AdEzN5MWh.jpg
https://ithelp.ithome.com.tw/upload/images/20201006/201198710TDtm7K4Hw.jpg

我們在繪圖時,如果一般使用畫線按座標的話,
通常是以plt.plot(x, y, linewidth)的型式,
此時就要剛好每個x的元素都對應到y的元素:

>>> x = np.arange(1, 9, 2)
>>> y = 2 * x
>>> plt.plot(x, y, linewidth=1.5) # 這樣應該是y=2x的樣子
[<matplotlib.lines.Line2D object at 0x000000000BCCB220>]
>>> plt.show()

https://ithelp.ithome.com.tw/upload/images/20201006/20119871LLSm0sNxrD.jpg
請留意一點,由於Python的陣列預設從0開始,所以當我們只給一段座標時,
會被當成y座標,且x會從0開始起算,以整數遞增:

>>> plt.plot([1,2,3,4])
>>> plt.show()
>>> plt.plot([1,2,3,4], [1,2,3,4]) # 留意X座標的變化!
>>> plt.show()

https://ithelp.ithome.com.tw/upload/images/20201007/20119871igHGgJqCDs.jpg
https://ithelp.ithome.com.tw/upload/images/20201007/20119871PPCBRudvNx.jpg

以plt.plot的方式繪圖時,畫上去的圖被稱為figure,
figure的軸則是axes,可以用add_subplot(1,1,1)方法取用到,
如果同時放多張子圖的話(1,1,1)代表第一張。
(這不是很好解釋,如果一次只畫一張圖的話就不管它啦!)
我們可以在繪製完圖以後再做額外的事情:

>>> fig = plt.figure()
>>> ax = fig.add_subplot(1,1,1)
>>> ax.plot([1,2,3,4], [1,2,3,4])
[<matplotlib.lines.Line2D object at 0x000000000B540B80>]
>>> ax.set_title('Title') # 表題
Text(0.5, 1.0, 'Title')
>>> ax.set_xlabel("label: x") # X軸文字
Text(0.5, 0, 'label: x')
>>> ax.set_ylabel("label: y") # Y軸文字
Text(0, 0.5, 'label: y')
>>> fig.suptitle('Sup Title', fontsize=20, fontweight='bold') # 
Text(0.5, 0.98, 'Sup Title')

https://ithelp.ithome.com.tw/upload/images/20201007/20119871dGSEwqCVL5.jpg

在plt.plot輸入陣列後加上一個格式字串可以用來代表畫線的樣式,
指定linewidth可以修改畫線的粗細。

# r代表紅色,x代表用'x'來表示點,且不畫線
>>> plt.plot([1,2,3,4], [3,5,15,18], 'rx')
[<matplotlib.lines.Line2D object at 0x000000000B856C10>]
# b代表藍色,'.'代表用單個小點表示一個點,'--'表示用虛線(dashed line)來畫線
>>> plt.plot([1,2,3,4], [3,9,1,6], 'b.--')
[<matplotlib.lines.Line2D object at 0x000000000B866310>]
# g代表綠色,o代表實心圓,linewidth表示粗度修為3
>>> plt.plot([1,2,3,4], [1,4,9,16], 'go-', linewidth=3) 
[<matplotlib.lines.Line2D object at 0x000000000B856F40>]
>>> plt.legend(('red', 'blue', 'green'), loc='upper left') # 畫圖例及決定位置
<matplotlib.legend.Legend object at 0x000000000B757730>
>>> plt.grid(True) # 畫出網格
>>> plt.show()

其結果應如下所示:
https://ithelp.ithome.com.tw/upload/images/20201007/20119871NDgzNbY1zv.jpg
在處理過後可畫線的圖以後,如果我們的資料是零散的點,
不需要畫線的話,我們可以用散點圖(scatter)來進行繪製:

>>> np.random.random(5)
array([0.22612501, 0.34256502, 0.21559228, 0.17675453, 0.1082928 ])
>>> x = np.random.random(500)
>>> y = np.random.random(500)
>>> plt.scatter(x, y) # 其實用plt.plot(x, y, 'o')也可以啦!
<matplotlib.collections.PathCollection object at 0x000000000B566580>
>>> plt.show()

如果要繪製3D的圖的話,要利用plt.axes(),
將其projection設為'3d'。
同時由於有三維座標,所以要使用ax.scatter3D(x, y, z, color)。

>>> z = np.random.normal(0, 0.2, 500)
>>> fig = plt.figure()
>>> ax = plt.axes(projection='3d')
>>> ax.scatter3D(x, y, z, color='blue')
<mpl_toolkits.mplot3d.art3d.Path3DCollection object at 0x000000000C00A1F0>
>>> plt.show()

最後我們會得到一個3D散點圖,其介面是可以按滑鼠左鍵拖曳旋轉的呦!
讀者可以自己嘗試看看~
https://ithelp.ithome.com.tw/upload/images/20201007/20119871SWV9C25a5X.jpg

其他其實還有相當多的內容,有興趣的話可以看看官方文件的說明。
像是各種不同種類的圖形、標記方式、標籤等等,
如果使用者想更進一步的話,可以試試看找一些如繪製股票線形的教學範例,
跟著操作看看,相信會更有收穫!

那麼,我們就明天見囉!


上一篇
[Day 26] 從零開始學Python - 科學運算NumPy:人間用多少滄桑,換多少人的瘋狂
下一篇
[Day 28] 從零開始學Python - 深度學習Keras:如果你能預知這條路的陷阱,我想你依然錯得很過癮
系列文
從零開始學Python30

尚未有邦友留言

立即登入留言