# matplotlib ## matplotlib 數據可視化 參考資料:https://matplotlib.org/stable/index.html ### matplotlib.pyplot.cla() & matplotlib.pyplot.clf() & matplotlib.pyplot.close() matplotlib.pyplot.cla():清除當前座標軸。 matplotlib.pyplot.clf():清除當前圖形。 matplotlib.pyplot.close():關閉整個視窗。 ### 做出一個簡易的一次函數圖形 ```python= import matplotlib.pyplot as plt import numpy as np x = np.linspace(-1, 1,50) y = 2*x+1 plt.plot(x,y) plt.show() ``` ![](https://i.imgur.com/9TR3rBw.png) 而若要做出檢簡易的二次函數,則只需更改y的值,將值設為二次方的數字 ### 同時顯示兩個figure ```python= import numpy as np import matplotlib.pyplot as plt x = np.linspace(-3,3,50) y1 = 2*x+1 y2 = x**2 plt.figure() plt.plot(x,y1) plt.figure(num = 3,figsize = (8,5)) plt.plot(x,y2) plt.plot(x,y1,color = 'yellow',linewidth = 1.0,linestyle = '-') plt.show() ``` plt.figure(num = 3,figsize = (8,5))裡第一個參數是figure的編號,第二個參數是調整視窗大小,plt.plot()的第一個參數是x座標,第二個參數是y座標,第三個參數是線條顏色,第四個參數是線條寬度,地五個參數是線條外觀。 ### subplot() subplot()的功能就是在同一個figure裡創造子圖,參數可放三個數字,分別代表「列數、行數、圖形編號」。 ### 顯示出自己限定的x和y的範圍 ```python= import matplotlib.pyplot as plt import numpy as np x = np.linspace(3, -3,50) y1 = 2*x+1 y2 = x**2 plt.figure() plt.plot(x,y2) plt.plot(x,y1,color = 'red',linewidth = 1.0,linestyle = '-') plt.xlim((-1,2)) plt.ylim((-2,3)) plt.show() ``` x座標顯示-1到2的範圍,y座標顯示-2到3的範圍 ### 顯示x和y的標籤 <span style = "color:red">xlabel</span> <span style = "color:red">ylabel</span> ```python= import matplotlib.pyplot as plt import numpy as np x = np.linspace(3, -3,50) y1 = 2*x+1 y2 = x**2 plt.figure() plt.plot(x,y2) plt.plot(x,y1,color = 'red',linewidth = 1.0,linestyle = '-') plt.xlim((-1,2)) plt.ylim((-2,3)) plt.xlabel('long') plt.ylabel('length') plt.show() ``` ![](https://i.imgur.com/lUSFAOV.png) ### 更換單位 <span style = "color:red">xticks</span> <span style = "color:red">yticks</span> ```python= import matplotlib.pyplot as plt import numpy as np x = np.linspace(3, -3,50) y1 = 2*x+1 y2 = x**2 plt.figure() plt.plot(x,y2) plt.plot(x,y1,color = 'red',linewidth = 1.0,linestyle = '-') plt.xlim((-1,2)) plt.ylim((-2,3)) plt.xlabel('long') plt.ylabel('length') new_ticks = np.linspace(-1,2,5) print(new_ticks) plt.xticks(new_ticks) plt.yticks([-2,-1.5,-1,1.2,3],['worst','bad','normal','good','best']) plt.show() ``` ![](https://i.imgur.com/5uAAdvv.png) ### 更改字體&特別符號 ```python= import matplotlib.pyplot as plt import numpy as np x = np.linspace(3, -3,50) y1 = 2*x+1 y2 = x**2 plt.figure() plt.plot(x,y2) plt.plot(x,y1,color = 'red',linewidth = 1.0,linestyle = '-') plt.xlim((-1,2)) plt.ylim((-2,3)) plt.xlabel('long') plt.ylabel('length') new_ticks = np.linspace(-1,2,5) print(new_ticks) plt.xticks(new_ticks) plt.yticks([-2,-1.5,-1,1.2,3],[r'$worst$',r'$bad$',r'$\alpha$',r'$good$',r'$best$']) plt.show() ``` 第16行的r為前置字元,且第三個為數學符號alpha,在alpha前加一個跳脫字元即可顯示希臘字母α。 ### 顯示座標軸 會使用到gca(get current axis) ```python= import matplotlib.pyplot as plt import numpy as np x = np.linspace(3, -3,50) y1 = 2*x+1 y2 = x**2 plt.figure() plt.plot(x,y2) plt.plot(x,y1,color = 'red',linewidth = 1.0,linestyle = '-') plt.xlim((-1,2)) plt.ylim((-2,3)) plt.xlabel('long') plt.ylabel('length') new_ticks = np.linspace(-1,2,5) print(new_ticks) plt.xticks(new_ticks) plt.yticks([-2,-1.5,-1,0,1.2,3],[r'$worst$',r'$bad$',r'$\alpha$',r'$o$',r'$good$',r'$best$']) ax = plt.gca() ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.xaxis.set_ticks_position('bottom') ax.spines['bottom'].set_position(('data',0)) ax.yaxis.set_ticks_position('left') ax.spines['left'].set_position(('data',0)) plt.show() ``` set_position語法:set_position(type=位置類型,amount=數量) outward:place the spine out from the data area by the specified number of points. axes: place the spine at the specified Axes coordinate (from 0.0-1.0) data:place the spine at the specified data coordinat ### 加圖例 <span style = "color:red">plt.legend()</span> ```python= import matplotlib.pyplot as plt import numpy as np x = np.linspace(-3,3,50) y1 = 2*x+1 y2 = x**2 plt.xlim((-1,2)) plt.ylim((-2,3)) plt.xlabel('x coordinate') plt.ylabel('y coordinate') new_ticks = np.linspace(-1,2,5) plt.xticks(new_ticks) plt.yticks([-2,-1.5,-1,0,1.2,3],[r'$worst$',r'$bad$',r'$\alpha$',r'$o$',r'$good$',r'$best$']) plt.figure() line1, = plt.plot(x,y2,label = 'up') # plt.plot() actually have a returns line2, = plt.plot(x,y1,color = 'green',linewidth = 1,linestyle = '--',label = 'down') plt.legend(handles = [line1,line2],labels = ['Quadratic function','linear function'],loc = 'best') # if you just want to have one legend you can change the parameter of labels,for examples:labels = ['Quadratic function,'] ,remember to add a comma after the first label plt.show() ``` ![](https://i.imgur.com/F2F0Dxw.png) ### 圖像做局部的註釋(annotation) plt.plot()是將整個函式圖形用線畫出來,若使用plt.scatter()則會將使用者提供的點繪出,不會自動將他話成一個直線,所以我們這邊使用plt.scatter()來做局部點的顯現,plt.scatter()的第一個參數放X座標,第二個放Y座標,第三個參數可以放尺寸,s = 尺寸,第四個參數可以放顏色,然而plt.scatter()還有更多參數,這邊只先用這幾個。接著我們再為圖像增加更多輔助,我們加入plt.plot([x0,x0],[y0,0],'k--',lw = 2.5)、plt.plot([0,x0],[y0,y0],'k--',lw = 2,color = 'purple')是為了輔助觀看,在圖中為點做延伸,第一個參數是放x座標的起點到終點,第二個參數是放y座標的起點和終點,第三個參數是放線條的樣式,第四個是放線條的尺寸。 ```python= import matplotlib.pyplot as plt import numpy as np x = np.linspace(-3,3,50) y = 2*x+1 plt.figure() plt.plot(x,y,color = 'r') ax = plt.gca() ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') ax.spines['bottom'].set_position(('data',0)) ax.spines['left'].set_position(('data',0)) x0 = 1 y0 = 2*x0+1 plt.scatter(x0,y0,s = 50,color = 'b') plt.plot([x0,x0],[y0,0],'k--',lw = 2) plt.plot([0,x0],[y0,y0],'k--',lw = 2,color = 'purple') plt.show() ``` ![](https://i.imgur.com/hJM8tHr.png) 接著進入註釋的部分,這裡會用到一個函式,plt.annotate(),先來看範例: ```python= import matplotlib.pyplot as plt import numpy as np x = np.linspace(-3,3,50) y = 2*x+1 plt.figure() plt.plot(x,y,color = 'r') ax = plt.gca() ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') ax.spines['bottom'].set_position(('data',0)) ax.spines['left'].set_position(('data',0)) x0 = 1 y0 = 2*x0+1 plt.scatter(x0,y0,s = 50,color = 'b') plt.plot([x0,x0],[y0,0],'k--',lw = 2) plt.plot([0,x0],[y0,y0],'y--',lw = 2) plt.annotate(r'2x+1 = %s' % y0,xy = (x0,y0),xycoords = 'data',xytext = (+30,-30),textcoords = 'offset points',fontsize = 20,arrowprops = dict(arrowstyle = '->',connectionstyle = 'arc3,rad = .2')) plt.show() ``` 把目光放在21行,那行的參數就是控制我們到時輸出的樣式,我先將程式碼寫出來: <span style = "color:blue">plt.annotate(r'2x+1 = %s' % y0,xy = (x0,y0),xycoords = 'data',xytext = (+30,-30),textcoords = 'offset points',fontsize = 20,arrowprops = dict(arrowstyle = '->',connectionstyle = 'arc3,rad = .2'))</span> 可以看到這段程式碼很大一串,但實際上不難理解,我們慢慢來看。 首先看到第一個參數,我們輸入一段文字,這段文字將會顯示於我們的figure上,我們利用%s,在後面加入一個變數,代表%s的地方就是y0,有學過C語言的應該對這邊不陌生吧! 接著看到第二個參數,xy,這個部分代表我們的文字要放在哪個座標上,我輸入x0和y0代表我的文字要在(x0,y0)上。 第三個參數就是我們被註釋點的座標系屬性,雖然它裡面可以放許多屬性,但這裡只使用data這個屬性,代表以被註釋的xy為參考。 第四個參數代表我的文字的位置更改,如果單純使用座標來定義位置的話可能會擋到我的圖像,或者在位置定義上不是那麼方便清楚,所以我們使用xytext()來調整我們文字的位置要在我們原本定義的座標的正、負多少的位置。 第五個參數是做字的調整。 第六個參數就是字體大小。 第七個參數是改變箭頭的形式,要注意這裡是一個字典(dict),而我這邊第一個參數是箭頭的樣式,第二個參數connectionstyle是我的箭頭有沒有弧度或者有其他的樣式,我這邊是調整使他有弧度。 ```python= import matplotlib.pyplot as plt import numpy as np x = np.linspace(-3,3,50) y = 2*x+1 plt.figure() plt.plot(x,y,color = 'r') ax = plt.gca() ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') ax.spines['bottom'].set_position(('data',0)) ax.spines['left'].set_position(('data',0)) x0 = 1 y0 = 2*x0+1 plt.scatter(x0,y0,s = 50,color = 'b') plt.plot([x0,x0],[y0,0],'k--',lw = 2) plt.plot([0,x0],[y0,y0],'y--',lw = 2) plt.annotate('2x+1 = %s' % y0,xy = (x0,y0),xycoords = 'data',xytext = (+30,-30),textcoords = 'offset points',fontsize = 20,arrowprops = dict(arrowstyle = '->',connectionstyle = 'arc3,rad = .2')) plt.text(-3,3,r'$I\ am\ a\ text$',color = "red",fontsize = 20) plt.show() ``` 我們也可以像第22行一樣使用plt.text()來做註釋,首先第一和二個參數是xy的座標,接下來得參數可以擺字體的調整,也可以直接使用fontdicr{'size':20,'color':'r'}來當參數引用。 輸出的圖: ![](https://i.imgur.com/kN3kQZD.png) ### 單位ticks被擋住(ticks能見度) ```python= import matplotlib.pyplot as plt import numpy as np x = np.linspace(-3,3,50) y = 2*x+1 plt.figure() plt.plot(x,y,color = 'r',linewidth = 20,zorder = 1) ax = plt.gca() ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.xaxis.set_ticks_position('bottom') ax.spines['bottom'].set_position(('data',0)) ax.yaxis.set_ticks_position('left') ax.spines['left'].set_position(('data',0)) for label in ax.get_xticklabels() + ax.get_yticklabels(): label.set_fontsize(12) label.set_bbox(dict(facecolor = 'yellow',edgecolor = 'black',alpha = 0.7)) plt.show() ``` 當你的單位被擋住了,可以使用16\~18行這幾行程式碼來使ticks更讓人看的更清楚,然後要注意第6行的plt.plot()要加zorder這個參數,這個參數的作用是控制圖層順序,簡單的說就是順序調整,接這看回16~18行,這裡用一個迴圈跑,保證x和y的ticks都有被設定到,17行set_fontsize()是設定字體大小,而set_bbox()是設定ticks的一些資料,記得這裡是一個字典,首先第一個參數的作用是ticks的背景顏色,而第二個參數是邊框顏色,第三個參數是ticks的能見度。 ![](https://i.imgur.com/RJ8KO41.png) ### scatter散點圖 今天如果要畫一個點狀散佈圖,可以使用scatter()函式,而我要的是隨機散佈圖,所以這邊使用random函式。 ```python= import matplotlib.pyplot as plt import numpy as np data_size = 1024 x = np.random.normal(0,1,data_size) y = np.random.normal(0,1,data_size) dot_color = np.arctan2(x,y) plt.scatter(x,y,s = 60,c = dot_color,alpha = 0.5) plt.xlim((-2,2)) plt.ylim((-2,2)) plt.xticks(()) plt.yticks(()) plt.show() ``` ![](https://i.imgur.com/mmwus8j.jpg) 而如果是要畫連續的點,則可以用arange()創造出連續的點。 ```python= import matplotlib.pyplot as plt import numpy as np x = np.arange(10) y = np.arange(10) plt.scatter(x,y) plt.show() ``` ![](https://i.imgur.com/GzWE2Pu.png) ### 繪製長條圖 我們如果畫長條圖,可以使用plt.bar(),首先我們要有x座標和y座標,製造出xy座標後將座標加入bar裡,而bar裡的facecolor和edgecolor分別代表長條圖背景顏色和邊框顏色,最後再用一個迴圈將每一個值輸出即可。 ```python= import matplotlib.pyplot as plt import numpy as np n = 12 x = np.arange(n) y = (1-x/float(n))*np.random.uniform(0.5,1.0,n) plt.bar(x,y,facecolor = '#9999ff',edgecolor = 'black') for i,j in zip(x,y): plt.text(i,j+0.01,'%.2f' % j,ha = 'center',va = 'bottom') plt.xticks(()) plt.yticks(()) plt.ylim((0,1.1)) plt.show() ``` ![](https://i.imgur.com/RUlxd9p.png) ### 繪出等高線圖 在matplotlib有許多函式可以繪出等高線圖,例如contour()、contourf()、tricontour()、tricontourf(),contour()、contourf()在帶入參數的時候是要帶入一個網格,而tricontour()、tricontourf()在帶入的時候只需帶入xlist、ylist、zlist即可,但contour()、contourf()的效果比較好,所以這邊會使用contour()、contourf()來繪製。 ```python= import matplotlib.pyplot as plt import numpy as np def height(x,y): return (1-x/2+x**5+y**3)*np.exp(-x**2-y**2) n = 512 x = np.linspace(-5, 5, n) y = np.linspace(-5, 5, n) x1, y1 = np.meshgrid(x,y) plt.contourf(x1, y1, height(x1,y1),10,alpha = 0.75,cmap = plt.cm.cool) c = plt.contour(x1,y1,height(x1,y1),10,colors = 'black',linewidth = 0.5) plt.clabel(c,inline = True,fontsize = 10) plt.xticks(()) plt.xlim((3,-3)) plt.ylim((3,-3)) plt.yticks(()) plt.show() ``` 首先我們可以看到我定義一個function,這個function可以自訂,作用是算出高度,所以我們將xy帶入,它可以算出等高線高度,不同function有不同效果。接定義一個n代表xy的數量,然後我為了製造出網格的形式,所以使用meshgrid(),它可以把我的list變成網格,所以將x,y帶入,而x1,y1就成了網格,接著將我的網格帶入contour()、contourf(),contourf()的第三個參數是放等高線的高度,所以我們用自訂函式來回傳數值,第四個參數是說我們的圖片要分割成幾塊,越多塊的時候越密集,第五個參數是透明度,最後一個參數控制我們等高線圖的顏色,運用到cmap,意思是說當我數值是a,會對應到b的顏色,就像是dict。接著是contour的部分,這邊是控制線條,且他會有數值的回傳值,所以我們用一個變數c來做存取,而它的參數跟contourf類似,這邊就不多做贅述。 最後的clabel是我們等高線上的數值,第一個參數要傳入數值,所以我們將剛剛的c傳入,第二個參數是說我們的數字要顯示在等高線條上,還是有數字的地方不要有線條經過,True代表不要有線條經過,False代表要有線條經過,最後一個參數是數字大小,做完後即完成等高線圖。 ![](https://i.imgur.com/QzVenGI.png) ### 製作出顏色圖片 ```python= import matplotlib.pyplot as plt import numpy as np a = np.array([0.33759320,0.63967205,0.40184628,0.64918592,0.49503721,0.44839065,0.35820281,0.53840583,0.38305164]).reshape(3,3) plt.imshow(a,interpolation = 'spline36',cmap = 'bone',origin = 'upper') plt.colorbar(shrink = 0.9) plt.xticks(()) plt.yticks(()) plt.show() ``` ![](https://i.imgur.com/6yKsbyn.jpg) 首先我們要建造一個array裡面存放一些數據,這些數據是為了建造出深淺不一的顏色,接著用reshape()來更改它的維度,接著使用imshow()來顯示出圖片,我們在imshow()的第一個參數加入剛剛設定好的array,第二個參數輸入你想要的顯示方式,有許多種,可以參考[這裡](https://matplotlib.org/2.0.2/examples/images_contours_and_fields/interpolation_methods.html)來查看其他種形式,第三個輸入你要的顏色形式,第四個加入你顏色的大小排序。 最後輸入plt.colorbar()可以顯示旁邊的顏色數值對照圖,加入的第一個參數是將對照圖的大小進行壓縮。 ### 製作3D圖片 ```python= import matplotlib.pyplot as plt import numpy as np from mpl_toolkits.mplot3d import Axes3D fig = plt.figure() ax = Axes3D(fig) x = np.arange(-4,4,0.25) y = np.arange(-4,4,0.25) x,y = np.meshgrid(x,y) tmp = np.sqrt(x**2+y**2) z = np.sin(tmp) ax.plot_surface(x,y,z,rstride = 1,cstride = 1,cmap = plt.get_cmap('rainbow')) ax.contourf(x,y,z,zdir = 'z',offset = -2,cmap = 'rainbow') ax.set_zlim(-2,2) plt.show() ``` 繪製3D圖需先引入一個第三方套件,from mpl_toolkits.mplot3d import Axes3D,接著先製作出一個空的figure,我將它存入fig,然後把他傳入Axis3D(),而Axis3D()有一個回傳值,我將它存入ax,接著建造x和y,接著的tmp和z是為了達成三維空間,所以要建造出一個z座標,然後ax.plot_surface()的第一和二和三個參數加入xyz值,第四和五個參數是說它橫跨的寬度是多少,注意,這邊一定要填入整數。ax.contourf()就像是建造等高線一樣,只是這邊要加入z值,最後設置一下視野就完成了,這個圖可以移動來看不同角度喔! ![](https://i.imgur.com/CM1f0Ju.jpg) ![](https://i.imgur.com/MhnXcu4.png)