Max Coding blog

Matplotlib

2021/08/27

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():關閉整個視窗。 ### 做出一個簡易的一次函數圖形

1
2
3
4
5
6
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()
而若要做出檢簡易的二次函數,則只需更改y的值,將值設為二次方的數字

同時顯示兩個figure

1
2
3
4
5
6
7
8
9
10
11
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的範圍

1
2
3
4
5
6
7
8
9
10
11
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的標籤 xlabel ylabel
1
2
3
4
5
6
7
8
9
10
11
12
13
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()
### 更換單位 xticks yticks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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()
### 更改字體&特別符號
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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

加圖例

plt.legend()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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()
### 圖像做局部的註釋(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座標的起點和終點,第三個參數是放線條的樣式,第四個是放線條的尺寸。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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()
接著進入註釋的部分,這裡會用到一個函式,plt.annotate(),先來看範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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行,那行的參數就是控制我們到時輸出的樣式,我先將程式碼寫出來: 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')) 可以看到這段程式碼很大一串,但實際上不難理解,我們慢慢來看。 首先看到第一個參數,我們輸入一段文字,這段文字將會顯示於我們的figure上,我們利用%s,在後面加入一個變數,代表%s的地方就是y0,有學過C語言的應該對這邊不陌生吧! 接著看到第二個參數,xy,這個部分代表我們的文字要放在哪個座標上,我輸入x0和y0代表我的文字要在(x0,y0)上。 第三個參數就是我們被註釋點的座標系屬性,雖然它裡面可以放許多屬性,但這裡只使用data這個屬性,代表以被註釋的xy為參考。 第四個參數代表我的文字的位置更改,如果單純使用座標來定義位置的話可能會擋到我的圖像,或者在位置定義上不是那麼方便清楚,所以我們使用xytext()來調整我們文字的位置要在我們原本定義的座標的正、負多少的位置。 第五個參數是做字的調整。 第六個參數就是字體大小。 第七個參數是改變箭頭的形式,要注意這裡是一個字典(dict),而我這邊第一個參數是箭頭的樣式,第二個參數connectionstyle是我的箭頭有沒有弧度或者有其他的樣式,我這邊是調整使他有弧度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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'}來當參數引用。 輸出的圖: ### 單位ticks被擋住(ticks能見度)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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的能見度。 ### scatter散點圖 今天如果要畫一個點狀散佈圖,可以使用scatter()函式,而我要的是隨機散佈圖,所以這邊使用random函式。
1
2
3
4
5
6
7
8
9
10
11
12
13
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()
而如果是要畫連續的點,則可以用arange()創造出連續的點。
1
2
3
4
5
6
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
y = np.arange(10)
plt.scatter(x,y)
plt.show()
### 繪製長條圖 我們如果畫長條圖,可以使用plt.bar(),首先我們要有x座標和y座標,製造出xy座標後將座標加入bar裡,而bar裡的facecolor和edgecolor分別代表長條圖背景顏色和邊框顏色,最後再用一個迴圈將每一個值輸出即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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()
### 繪出等高線圖 在matplotlib有許多函式可以繪出等高線圖,例如contour()、contourf()、tricontour()、tricontourf(),contour()、contourf()在帶入參數的時候是要帶入一個網格,而tricontour()、tricontourf()在帶入的時候只需帶入xlist、ylist、zlist即可,但contour()、contourf()的效果比較好,所以這邊會使用contour()、contourf()來繪製。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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代表要有線條經過,最後一個參數是數字大小,做完後即完成等高線圖。 ### 製作出顏色圖片
1
2
3
4
5
6
7
8
9
10
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()
首先我們要建造一個array裡面存放一些數據,這些數據是為了建造出深淺不一的顏色,接著用reshape()來更改它的維度,接著使用imshow()來顯示出圖片,我們在imshow()的第一個參數加入剛剛設定好的array,第二個參數輸入你想要的顯示方式,有許多種,可以參考這裡來查看其他種形式,第三個輸入你要的顏色形式,第四個加入你顏色的大小排序。 最後輸入plt.colorbar()可以顯示旁邊的顏色數值對照圖,加入的第一個參數是將對照圖的大小進行壓縮。 ### 製作3D圖片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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值,最後設置一下視野就完成了,這個圖可以移動來看不同角度喔!

by 中和高中 吳振榮
CATALOG
  1. 1. matplotlib 數據可視化
    1. 1.1. 同時顯示兩個figure
    2. 1.2. 顯示座標軸
    3. 1.3. 加圖例
      1. 1.3.0.1. by 中和高中 吳振榮