Matplotlib基本使用簡介
1. Matplotlib簡介
Matplotlib是Python的一個2D圖形庫,能夠生成各種格式的圖形(諸如折線圖,散點圖,直方圖等等),界面可交互(可以利用鼠標對生成圖形進行點擊操作),同時該2D圖形庫跨平台,即既可以在Python腳本中編碼操作,也可以在Jupyter Notebook中使用,以及其他平台都可以很方便的使用Matplotlib圖形庫,而且生成圖形質量較高,甚至可以達到出版級別。需要注意的是,在相關Python軟件中調用Matplotlib圖形庫時,需要利用shell進行單獨安裝,假如使用Jupyter Notebook時,相關圖形庫已直接配置在軟件內,不過其生成的圖形無法進行交互,而是內嵌在Jupyter Notebook生成界面內。
針對Matplotlib的官方說明如下所示:
Matplotlib is a Python 2D plotting library which produces publication quality figures in a variety of hardcopy formats and interactive environments across platforms. Matplotlib can be used in Python scripts, the Python and IPython shells, the Jupyter notebook, web application servers, and four graphical user interface toolkits.
2. Matplotlib操作簡介
2.1 Matplotlib示例
在Python中使用Matplotlib時,常用到Matplotlib模塊和Numpy模塊,下面以一個簡單的線性圖形的例子進行說明:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3,3.50)
y_1 = 2*x+1
plt.plot(x,y_1)
plt.show()
通過上述生成如下一次函數圖形,首先對上述代碼進行簡要解說:
- 首先繪圖需要導入matplotlib.pyplot,其中pyplot是matplotlib的繪圖框架,功能類似於於MATLAB的繪圖功能,圖形繪制需要利用到pyplot,即 plt.plot()和plt.show();
- 程序通過Numpy生成繪圖所需數據,Numpy是Python的一個數據處理包,極大的方便了Python在科學計算方面的應用,在程序中通過使用Numpy內置 linspace()生成區間在[-3,3]的數組。
假如需要圖像上具有多個函數圖形,可進行如下操作:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3,3.50)
y_1 = 2*x+1
y_2 = x**2
# plt.figure(num=1,figsize=(8,5))
plt.plot(x,y_1)
plt.plot(x,y_2)
plt.show()
如上述代碼所示,只需在上述兩個函數后進行兩次圖像繪制即可實現復合圖像的生成。
2.2 Matplotlib參數設置
前面通過簡單示例對Matplotlib進行初步的講解,但仔細觀察后,圖1仍缺失很多繪圖屬性元素,下面將對Matplotlib中的繪圖屬性進行簡要介紹:
2.2.1 軸線設置
(1)軸線范圍及標簽設置
首先進行坐標軸設置的解讀,主要涉及坐標范圍,數值,刻度修改和坐標軸顯示等多個方面。
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3,3.50)
y_1 = 2*x+1
plt.plot(x,y_1)
# 坐標軸設置
# 坐標軸范圍
plt.xlim(-1,2)
plt.ylim(-2,3)
# 坐標軸標簽
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.show()
通過對比圖1和圖3可以發現,相較於圖1,圖二刻度值范圍改變,而且在坐標軸底側和左側分別增加了X Axis 和 Y Axis 兩個軸標簽。此處用到幾個方法:
坐標軸范圍設置: xlim() 和 ylim();
坐標軸標簽設置:xlabel() 和 ylabel();
(2)軸線刻度值修改
上述進行坐標軸區間設置和標簽的添加,有時候我們還會遇到這樣兩種情況:
- 由於坐標軸的單位刻度不當,導致圖形不美觀或者信息缺失;
- 需要對坐標軸上某個值進行修改或替換;
針對上述第一種情況,下面通過相應的函數來處理:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3,3.50)
y_1 = 2*x+1
plt.plot(x,y_1)
# 坐標軸設置
# 坐標軸刻度修改
new_ticks = np.linspace(-1,2,5)
plt.xticks(new_ticks)
plt.yticks([-2,-1.5,0,1,2])
# 坐標軸標簽
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.show()
例子中使用到以下兩個方法:
坐標軸刻度值修改:xticks() 和 yticks();
通過將替換刻度數據鍵入上述兩個方法中,然后進行顯示(只有plt.show()之后才能顯示修改),原刻度值即可被修改。
(3)軸線刻度值替換
針對上述的第二種情況,下述代碼將給出詳細的講解:
import matplotlib.pyplot as plt
import numpy as np
# 坐標軸設置
# 坐標軸刻度值替換
# 示圖1(見圖5)
x = np.linspace(-3,3.50)
y_1 = 2*x+1
plt.plot(x,y_1)
new_ticks = np.linspace(-1,2,5)
plt.xticks(new_ticks)
plt.yticks([-2,-1.5,0,1,2],['bad','not bad','normal','good','best'])
plt.show()
# 示圖2(見圖6)
x = np.linspace(-3,3.50)
y_1 = 2*x+1
plt.plot(x,y_1)
new_ticks = np.linspace(-1,2,5)
plt.xticks(new_ticks)
plt.yticks([-2,-1.5,0,1,2],[r'$bad$',r'$not\ bad$',r'$normal$',r'$good$',r'$best$'])
plt.show()
# 示圖3(見圖7)
x = np.linspace(-3,3.50)
y_1 = 2*x+1
plt.plot(x,y_1)
new_ticks = np.linspace(-1,2,5)
plt.xticks(new_ticks)
plt.yticks([-2,-1.5,0,1,2],[r'$alpha$',r'$\beta$',r'$\theta$',r'$\gamma$',r'$\phi$'])
# 坐標軸標簽
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.show()
在上述代碼中,坐標值替換發生在y軸,首先能夠確定的事,進行替換的字符需要與相應的坐標值一一對應,這是首要的原則,接下來對不同的字符替換形式進行了簡單的嘗試:
- 第一種只進行字符的對應,沒有進行其他符號處理(即未添加$處理),結果顯示替換字符為一般的字體;
- 第二種對替換字符進行了數學符號的處理(即添加$進行標注),結果顯示為斜體,同時需要輸入空格時,需要在空格前添加反斜杠 **\ **;
- 第三種進行希臘字母的輸出,規則是在希臘字母英語讀法前添加反斜杠 **\ **,假如不添加,則會輸出第二種字母斜體。
在代碼中,在處理字符前還添加有r ,它表示正則化,假如不添加在上述例子中也不影響,至於具體作用,在此不過多介紹,感興趣的人可以自查資料。
(4)軸線隱去設置
在實際應用我們還會遇到這兩種圖形:
- 圖像只需要坐標軸xy所在軸的框線;
- 圖形貫穿多個象限,即此時在圖像上需要顯示多個象限,換而言之就是需要挪動坐標軸位置;
下面首先針對第一個問題進行簡要介紹:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3,3.50)
y_1 = 2*x+1
plt.plot(x,y_1)
# 去除多余坐標軸
# gca = 'get current axis'
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
plt.show()
去除不需要的坐標軸不是真的將其“刪除”,而是將其變為無色,使之與底圖背景色相同。在該處理過程中,主要使用到了以下幾種方法:
激活當前坐標軸:gca()
軸線選取選項:spine(),選項有(top、bottom、left、right)
顏色設置選項:set_color(),當為none時,表示為無色
(5)軸線移動設置
經過坐標軸線的去除處理,接下來移動坐標軸就很方便:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3,3.50)
y_1 = 2*x+1
plt.plot(x,y_1)
# 去除多余坐標軸
# gca = 'get current axis'
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')
# 進行坐標軸的移動-data
ax.spines['bottom'].set_position(('data',0))
# ax.spines['left'].set_position(('data',0))
plt.show()
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3,3.50)
y_1 = 2*x+1
plt.plot(x,y_1)
# 去除多余坐標軸
# gca = 'get current axis'
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')
# 進行坐標軸的移動-axes
ax.spines['bottom'].set_position(('axes',0.5))
# ax.spines['left'].set_position(('axes',0.5))
plt.show()
在上述代碼中,移動坐標軸需要經過以下幾個步驟:
隱去非坐標軸框線 —> 確定待移動的坐標軸 —> 移動坐標軸
第一步在圖7中已經進行了處理,在第二步和第三步中用到了一下幾個方法:
將“bottom”作為x軸移動:ax.xaxis.set_ticks_position('bottom')
移動作為x軸的軸線“bottom”:ax.spines['bottom'].set_position(('data',0))
此處需要強調下set_position()方法,該方法中具有三個參數,即data,outward 和axes。
- 針對data ,對比圖9和圖10,當進行bottom或者left軸設置時,處理效果為移動相應坐標軸到坐標刻度為0的位置。
- 針對axes,首先參數axes的取值范圍為0~1,對比圖11和圖12,axes的移動規則與data相同,但是axes所取小數為整個坐標軸的比例位置,從負數方向向正數方向增加。由於坐標軸中點位置並非原點位置,所以出現了圖10和圖11所示現象。
- 針對outward,此處由於自己理解不到位,所以此處不在進行贅述,但能說道的一點就是系統默認outward=0。
- 另外為了方便書寫,Matplotlib定義了一些簡寫符號:'center' -> ('axes',0.5) 和 'zero' -> ('data', 0.0)
(6)主次坐標軸
我們在作圖時還會遇到一些共軸圖像,即圖像上具有多個函數圖像,函數圖像橫坐標值數據相同,但是縱坐標值不同,此處進行次坐標軸(secondary axis) 的簡單講述:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0,10,.1)
y_1 = 0.05*x**2
y_2 = -1*y_1
fig,ax_1 = plt.subplots()
ax_2 = ax_1.twinx()
ax_1.plot(x,y_1,'g-')
ax_2.plot(x,y_2,'b--')
ax_1.set_xlabel('X data')
ax_1.set_ylabel('Y_1',color='g')
ax_2.set_ylabel('Y_2',color='b')
plt.show()
如上圖和代碼所示,Y_1圖像用 left 軸,Y_2圖像使用 right 軸,整個程序中除 figure 和 twinx() 兩種方法外,其余代碼在前面已講解,figure 將在圖像一節中進行詳細講解,此處主要對方法 twinx() 進行簡要的說明:
- 代碼 ax_2 = ax_1.twinx() 中,twinx() 的作用主要是將坐標軸ax_1“鏡像”給ax_2,此處“鏡像”不僅僅是坐標軸線,而是連同坐標軸的特性一並“鏡像”過來。
2.2.2 圖例設置
圖例是圖像中必不可少的元素,接下來將對圖像標簽的設置進行簡單的講解,在講解之前首先進行復合圖像,即同一圖中具有多條函數曲線的講解:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0,10,.1)
y_1 = 0.05*x**2
y_2 = -1*y_1
# 第一種表示
plt.plot(x,y_1,'g-',label='y_1')
plt.plot(x,y_2,'b--',label='y_2')
plt.legend(loc='best')
# 第二種表示
# l_1, = plt.plot(x,y_1,'g-')
# l_2, = plt.plot(x,y_2,'b--')
# plt.legend(handles=[l_1,l_2],labels=['y_1','y_2'],loc='best')
plt.xlabel('X data')
plt.ylabel('Y data')
plt.show()
觀察圖14,圖中標簽被放置在了左上方,標簽設置過程中主要使用了兩種表示形式,首先第一種涉及到了以下幾個方法:
- plt.plot(x,y_1,'g-',label='y_1') ,通過在 plot 中設置 label 顯示標簽名稱;
- plt.legend(loc='best'),通過方法 legend 進行標簽位置設置,代碼中使用了best ,即系統自動將標簽放置在空白較多的區域,位置設置主要有以下幾個:best、upper right、upper left、lower left、lower right、right、center left、center right、lower center、 upper center、center。
第二種主要涉及到了一下幾個方法:
-
handles 和 label,如代碼所示,在使用handles前先要進行相應的函數定義,按照定義方法,一般在定義名稱后加上英文輸入下的逗號,即l_1, 查找相關資料解釋說:
當要將 plot 函數 返回的結果保存下來,由於 plot 函數返回的是一個列表,所以需要添加逗號,或者在 plot 函數末尾添加 [0]。
但是並沒有真正的理解,僅供大家參考,同時在使用handles時,需要進行使用[ ],同理,label 進行標簽名稱設置時,也需要使用 [ ] 表示。
上面只是進行Legend的基本使用進行簡述,Legend還有其他相應的處理方法,假如感興趣,個人可以進一步研究,這里給出一個網上的詳細講解,方便大家學習,Legend Method。
2.2.3 標注設置
在繪圖過程中,我們有時會對圖像中的關鍵點或信息進行標注以示強調,接下來就對標注的具體過程進行簡要講述:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3,3,50)
y = 2*x + 1
plt.plot(x,y)
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))
# 特征點標注
x_0 = 1
y_0 = 2*x_0 + 1
# scatter是點畫線,即上述的plt.plot()可以寫成plt.scatter(),則會形成點划線
plt.scatter(x_0,y_0)
plt.plot([x_0,x_0],[y_0,0],'r--',lw=2.5) # 設置特征點到x軸的引線
# 關鍵點信息標注
# method_1
plt.annotate('$2x_0+1=%s$' %y_0,xy=(x_0,y_0),xycoords='data',xytext=(+30,-30),anncoords='offset points',fontsize=16,arrowprops=dict(arrowstyle='->',connectionstyle='arc3,rad=.2'))
# method_2
# plt.text(-3.7,3,r'$This\ is\ the\ some\ text.\ \mu\ \sigma_i\ \alpha_t$',fontdict={'size':14,'color':'r'})
plt.show()
代碼前半部分主要講述的是坐標軸的移動,從注釋開始進入特征點部分的書寫,觀察圖15,圖像標注主要分為兩部分:
- 關鍵點標注:如圖15右側,關鍵點的標注主要分為四部分,(1)關鍵點繪制;(2)關鍵點對齊線;(3)關鍵點公式和引線。
(1)關鍵點繪制:代碼中選取x=1處的坐標點;在突出顯示確定點時使用如下代碼 plt.scatter(x_0,y_0),即將確定點繪制成散點模式(scatter() 是繪制散點圖的方法)。
(2)關鍵點對齊線:plt.plot([x_0,x_0],[y_0,0],'r--',lw=2.5), # 設置特征點到x軸的引線,其中涉及到了線型的設置,即('r--',lw=2.5),線型將在2.2.4節進行講述,此處只需要知道在代碼中,線型被設置為紅色虛線繪制,線寬2.5;關於對齊線的畫法,代碼使用plot() 的方法,根據列表區間繪制線條,即引線橫坐標區間為x=1,縱坐標區間為[0,y_0]。
(3)關鍵點公式和引線:代碼中使用annotate 的方法,首先'2x_0+1=3' 的繪制方法同2.2.1節中所提到的利用$ 進行數學斜體的繪制方法,其次為標注信息的繪制,即首先確定繪制點,即 xy=(x_0,y_0),然后定位傳遞數據的坐標位置,即xycoords='data',然后確定標注式子的放置位置,即利用 xytext=(+30,-30),anncoords='offset points',fontsize=16 將標注公式放置在偏移關鍵點(x+30,y-30)的位置,然后利用arrowprops=dict(arrowstyle='->',connectionstyle='arc3,rad=.2')) 進行引線設置,首先設置引線的樣式,代碼中使用的是—>,而且引線呈弓線狀,即通過connectionstyle進行設置,弓線彎曲半徑0.2,即使用rad 進行設置。
上例只是進行簡單講解,其實包括引線形式,格式等還有很多,此處貼下兩篇博客供大家參考:Annotation_1、Annotation_2。
- 關鍵信息標注:設置方法與關鍵點的設置類似,此處通過另外使用fontdict 方法進行標注信息的格式設置,代碼進行了標准信息大小和顏色的設置,即size()、color()。
- 基於官方消息,xytext()和textcoords()在將來經不再提供支持,開始支持xyann()和anncoords()。
2.2.4 圖像設置
在圖形繪制中,我們經常會涉及到圖像分欄以及圖中圖等問題,接下來將對圖像的上述問題進行一一解讀。
(1)圖像尺寸及線型設置
首先講述下最簡單的問題,即對圖像的一些簡單設置進行簡要講解,主要涉及圖像大小設置和線型的設置:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3,3.50)
y_1 = 2*x+1
y_2 = x**2
plt.figure(num=1,figsize=(8,5))
plt.plot(x,y_1,color='r',linewidth=1.5,linestyle='--',marker='+')
plt.plot(x,y_2,color='g',linewidth=1.5,linestyle='-',marker='<')
plt.show()
上述代碼關於圖像設置主要涉及兩部分內容,即圖像編號及大小設置和圖像線性的設置:
- 圖像編號及大小的設置:plt.figure(num=1,figsize=(8,5)) 圖像中設置圖像需要用到figure() 方法,如需設置繪圖編號,可以利用參數 num 進行指定,未指定時,系統默認首圖為1,利用 figsize 可以進行圖像大小的設置,設置對象為整個軸線框的尺寸;
- 圖像線型設置:利用 plt.plot(x,y_1,color='r',linewidth=1.5,linestyle='--',marker='+') 將直線渲染成紅色,線寬1.5,線型為虛線,標記為‘+’ 的狀態。
針對顏色設置,可以寫成以下幾種形式:
(a) 使用顏色全稱代號,即color='r' 或者color='red';
(b) 使用顏色16進制,color='#FF0000’;
(c) 使用顏色RGB或RGBA元組,即 color=(1,0,0) 或 color=(1,0,0,1),前者為RGB模式,后者為RGBA模式,兩者前三個數字相同,RGBA模式的最后一個數字表示顏色的透明度,范圍是0~1。另外需要注意的是,Matplotlib中的RGB格式和常見的RGB格式不太相同,Matplotlib中的RGB數值均為 0~1,而我們常見的RGB格式為 0~255;
(d) 使用灰度強度進行表示:即 color=0.5,關於灰度值的具體定義和計算,可以參照相關資料,此處給出百度百科解釋:Gray。
(e) 針對常用顏色表示,此處給出圖例以示參考:
'aliceblue': '#F0F8FF' 'antiquewhite': '#FAEBD7' 'aqua': '#00FFFF' 'aquamarine': '#7FFFD4' 'azure': '#F0FFFF' 'beige': '#F5F5DC' 'bisque': '#FFE4C4' 'black': '#000000' 'blanchedalmond': '#FFEBCD' 'blue': '#0000FF' 'blueviolet': '#8A2BE2' 'brown': '#A52A2A' 'burlywood': '#DEB887' 'cadetblue': '#5F9EA0' 'chartreuse': '#7FFF00' 'chocolate': '#D2691E' 'coral': '#FF7F50' 'cornflowerblue': '#6495ED' 'cornsilk': '#FFF8DC' 'crimson': '#DC143C' 'cyan': '#00FFFF' 'darkblue': '#00008B' 'darkcyan': '#008B8B' 'darkgoldenrod': '#B8860B' 'darkgray': '#A9A9A9' 'darkgreen': '#006400' 'darkkhaki': '#BDB76B' 'darkmagenta': '#8B008B' 'darkolivegreen': '#556B2F' 'darkorange': '#FF8C00' 'darkorchid': '#9932CC' 'darkred': '#8B0000' 'darksalmon': '#E9967A' 'darkseagreen': '#8FBC8F' 'darkslateblue': '#483D8B' 'darkslategray': '#2F4F4F' 'darkturquoise': '#00CED1' 'darkviolet': '#9400D3' 'deeppink': '#FF1493' 'deepskyblue': '#00BFFF' 'dimgray': '#696969' 'dodgerblue': '#1E90FF' 'firebrick': '#B22222' 'floralwhite': '#FFFAF0' 'forestgreen': '#228B22' 'fuchsia': '#FF00FF' 'gainsboro': '#DCDCDC' 'ghostwhite': '#F8F8FF' 'gold': '#FFD700' 'goldenrod': '#DAA520' 'gray': '#808080' 'green': '#008000' 'greenyellow': '#ADFF2F' 'honeydew': '#F0FFF0' 'hotpink': '#FF69B4' 'indianred': '#CD5C5C' 'indigo': '#4B0082' 'ivory': '#FFFFF0' 'khaki': '#F0E68C' 'lavender': '#E6E6FA' 'lavenderblush': '#FFF0F5' 'lawngreen': '#7CFC00' 'lemonchiffon': '#FFFACD' 'lightblue': '#ADD8E6' 'lightcoral': '#F08080' 'lightcyan': '#E0FFFF' 'lightgoldenrodyellow': '#FAFAD2' 'lightgreen': '#90EE90' 'lightgray': '#D3D3D3' 'lightpink': '#FFB6C1' 'lightsalmon': '#FFA07A' 'lightseagreen': '#20B2AA' 'lightskyblue': '#87CEFA' 'lightslategray': '#778899' 'lightsteelblue': '#B0C4DE' 'lightyellow': '#FFFFE0' 'lime': '#00FF00' 'limegreen': '#32CD32' 'linen': '#FAF0E6' 'magenta': '#FF00FF' 'maroon': '#800000' 'mediumaquamarine': '#66CDAA' 'mediumblue': '#0000CD' 'mediumorchid': '#BA55D3' 'mediumpurple': '#9370DB' 'mediumseagreen': '#3CB371' 'mediumslateblue': '#7B68EE' 'mediumspringgreen': '#00FA9A' 'mediumturquoise': '#48D1CC' 'mediumvioletred': '#C71585' 'midnightblue': '#191970' 'mintcream': '#F5FFFA' 'mistyrose': '#FFE4E1' 'moccasin': '#FFE4B5' 'navajowhite': '#FFDEAD' 'navy': '#000080' 'oldlace': '#FDF5E6' 'olive': '#808000' 'olivedrab': '#6B8E23' 'orange': '#FFA500' 'orangered': '#FF4500' 'orchid': '#DA70D6' 'palegoldenrod': '#EEE8AA' 'palegreen': '#98FB98' 'paleturquoise': '#AFEEEE' 'palevioletred': '#DB7093' 'papayawhip': '#FFEFD5' 'peachpuff': '#FFDAB9' 'peru': '#CD853F' 'pink': '#FFC0CB' 'plum': '#DDA0DD' 'powderblue': '#B0E0E6' 'purple': '#800080' 'red': '#FF0000' 'rosybrown': '#BC8F8F' 'royalblue': '#4169E1' 'saddlebrown': '#8B4513' 'salmon': '#FA8072' 'sandybrown': '#FAA460' 'seagreen': '#2E8B57' 'seashell': '#FFF5EE' 'sienna': '#A0522D' 'silver': '#C0C0C0' 'skyblue': '#87CEEB' 'slateblue': '#6A5ACD' 'slategray': '#708090' 'snow': '#FFFAFA' 'springgreen': '#00FF7F' 'steelblue': '#4682B4' 'tan': '#D2B48C' 'teal': '#008080' 'thistle': '#D8BFD8' 'tomato': '#FF6347' 'turquoise': '#40E0D0' 'violet': '#EE82EE' 'wheat': '#F5DEB3' 'white': '#FFFFFF' 'whitesmoke': '#F5F5F5' 'yellow': '#FFFF00' 'yellowgreen': '#9ACD32'針對線型設置,主要有以下幾種:
- 實線 - - 短線 -. 短點相間線 : 虛點線 針對標記的設置如下所示:
'.' point marker ',' pixel marker 'o' circle marker 'v' triangle_down marker '^' triangle_up marker '<' triangle_left marker '>' triangle_right marker '1' tri_down marker '2' tri_up marker '3' tri_left marker '4' tri_right marker 's' square marker 'p' pentagon marker '*' star marker 'h' hexagon1 marker 'H' hexagon2 marker '+' plus marker 'x' x marker 'D' diamond marker 'd' thin_diamond marker '|' vline marker '_' hline marker
(2)圖像透明度設置
在實際繪圖中,由於某些原因造成所繪圖像的坐標軸信息(比如坐標值)被圖像所覆蓋,導致圖像質量下降,我們可以通過設置圖像透明度的問題來處理這種問題,接下來將對 圖像透明度進行簡要講解:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3,3,50)
y = 0.1*x
fig = plt.figure()
plt.plot(x,y,linewidth=10,alpha=0.8)
plt.ylim(-2,2)
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_family('monospace')
label.set_fontsize(12)
# alpha是調整透明度
label.set_bbox(dict(facecolor='grey',edgecolor='None',alpha=0.5))
plt.show()
如代碼所示,設置主要涉及以下幾個方面:
-
首先利用 plt.plot(x,y,linewidth=10,alpha=0.8) 進行圖像透明度的設置,其中設置透明度所用關鍵參數為 alpha,該值的范圍為0~1,數值越大,透明度越低。
-
其次涉及坐標軸數值的設置:
for label in ax.get_xticklabels() + ax.get_yticklabels(): # 設置字體 label.set_family('monospace') label.set_fontsize(12) # alpha是調整透明度 label.set_bbox(dict(facecolor='grey',edgecolor='None',alpha=0.5))如上述代碼所示,首先利用 get_xticklabels() 和 get_yticklabels() 獲得坐標軸數據,然后對坐標軸數據進行字體設置,主要用到 set_family() 和 set_fontsize(),前者設置字體格式,后者設置字體大小。最后利用set_bbox()對坐標軸數據繪制背景框,邊框內部顏色設置- facecolor() 和邊框框線設置 edgecolor(),需要說明的是,由於透明度設置不是很合理,所以圖17效果並不是很理想,但原理大致如上所講述。
(3)圖像分欄設置
接下來對 圖像分欄,即同一圖中具有多個分格圖像進行簡要講解:
import matplotlib.pyplot as plt
# 子圖均分
plt.subplot(2,2,1) # 2行2列
plt.plot([0,1],[0,1])
plt.subplot(222) # 可以去掉逗號,但是建議加上逗號
plt.plot([0,1],[0,1])
plt.subplot(223)
plt.plot([0,1],[0,1])
plt.subplot(224)
plt.plot([0,1],[0,1])
plt.show()
################################################
# 子圖不等均分
plt.subplot(2,1,1) # 2行1列
plt.plot([0,1],[0,1])
plt.subplot(234) # 按照索引值進行排列
plt.plot([0,1],[0,1])
plt.subplot(235)
plt.plot([0,1],[0,1])
plt.subplot(236)
plt.plot([0,1],[0,1])
plt.show()
圖18和圖19主要涉及圖像分欄顯示,主要涉及 subplot() 方法的使用,同時 subplot(a,b,c) 方法中a和b分別表示將圖像界面分為a行b列,而c表示將圖像放置在第幾個位置(按照行列號索引值進行排序),另外需要注意的是在數量不多情況下(abc 為10以內數字時)可以省略 abc 之間的逗號,當數量較多時可能會引發錯誤。下面在對圖像分欄顯示的不同形式簡要概述:
- 均勻分欄時,即圖18所示形式,確定好行列數后,c 范圍為[1,ab]*,同時先排行在排列;
- 不均勻分欄時,即圖19所示形式,在代碼中第一行使用 plt.subplot(2,1,1) 表示第一行第一列(首先將整個圖像區域分成了2行,該代碼占據了第一行),由於是在后面出現了plt.subplot(2,3,4),這意味着將第二行划分為3等分,但是計數從整個圖像開始計算,即(2,3),同時需要注意的是,由於從整體開始計數,所以第二行第一個列計數從第4個開始。
另外針對不均勻圖像分欄,上述方法使用不是很方便,此處再進行三種方法的詳細介紹:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
# method 1:subplot2grid
ax_1 = plt.subplot2grid((3,3),(0,0),colspan=3,rowspan=1)
ax_1.plot([1,2],[1,2])
ax_1.set_title('ax_1_title')
# (3,3)表示三行三列,(0,0)表示從0行0列開始,其中0,0是index
ax_2 = plt.subplot2grid((3,3),(1,0),colspan=2)
ax_3 = plt.subplot2grid((3,3),(1,2),rowspan=2)
ax_4 = plt.subplot2grid((3,3),(2,0))
ax_4 = plt.subplot2grid((3,3),(2,1))
plt.show()
# method 2:gridspec
plt.figure()
gs = gridspec.GridSpec(3,3)
ax_1 = plt.subplot(gs[0,:])
ax_2 = plt.subplot(gs[1,:2])
ax_3 = plt.subplot(gs[1:,2])
ax_4 = plt.subplot(gs[-1,0])
ax_5 = plt.subplot(gs[-1,-2])
plt.show()
# method 3:easy to define structure
f,((ax_1,ax_2),(ax_3,ax_4)) = plt.subplots(2,2,sharex=True,sharey=True)
ax_1.scatter([1,2],[1,2])
plt.tight_layout()
# fig1,f1_axes = plt.subplots(ncols=2,nrows=2,constrained_layout=True)
plt.show()
相較於直接使用subplot方法不等分圖像,上述三種方法更為便利:
-
首先觀察method_1中代碼:
ax_1 = plt.subplot2grid((3,3),(0,0),colspan=3,rowspan=1) ax_1.plot([1,2],[1,2]) ax_1.set_title('ax_1_title')代碼主要使用了subplot2grid 方法進行網格划分,官方定義為:
A helper function that is similar to subplot(), but uses 0-based indexing and let subplot to occupy multiple cells.
觀察圖20,ax_1圖像占據了第一行,圖像設置仍是將圖像整體划分成3行3列,即(3,3),然后ax_1圖像從(0,0)索引值開始放置(類似於列表索引,下標值從(0,0)開始,然后使用關鍵參數定義ax_1圖像的范圍,即colspan=3,rowspan=1(3列1行)。set_title() 是設置圖像標題方法。同理關於ax_2 和 ax_3 圖像設置方法相同。
-
其次觀察method_2中代碼:
plt.figure() gs = gridspec.GridSpec(3,3) ax_1 = plt.subplot(gs[0,:]) ax_2 = plt.subplot(gs[1,:2]) ax_3 = plt.subplot(gs[1:,2]) ax_4 = plt.subplot(gs[-1,0]) ax_5 = plt.subplot(gs[-1,-2])gridspec 方法是通過設置將圖像划分為特定的網格形狀,官方解釋為:
***Specifies the geometry of the grid that a subplot will be placed ***
首先通過 GridSpec 設置總的網格數量(以最小網格為單位),剩下的進行類似於列表的切片處理,如ax_1 = plt.subplot(gs[0,:]) 表示第1行的占據,ax_2 = plt.subplot(gs[1,:2]) 進行第2行,前兩列位置的占據,而ax_3 = plt.subplot(gs[1:,2]) 則進行第二行到最后一行的行位置占據和第三列位置的占據,上下的依次類推。
-
其次觀察method_3中代碼:
f,((ax_1,ax_2),(ax_3,ax_4)) = plt.subplots(2,2,sharex=True,sharey=True) ax_1.scatter([1,2],[1,2]) plt.tight_layout() # fig1,f1_axes = plt.subplots(ncols=2,nrows=2,constrained_layout=True)方法3主要涉及subplots 方法的使用,官方定義為:
***Perhaps the primary function used to create figures and axes. It’s also similar to
matplotlib.pyplot.subplot(), but creates and places all axes on the figure at once. ***- 首先 f, 是定義了一個圖像,其中 f 是figure 的縮寫,也可以寫成fig,然后設置2行2列的網格圖,四個網格圖共享xy軸,需要注意的是,為了使整個圖像更加的緊湊,代碼使是用了plt.tight_layout(),個人感興趣的話可以自己觀察。
- 我們也可以使用另外一種表示方式,即通過使用下述代碼進行圖像設置:fig1,f1_axes=plt.subplots(ncols=2,nrows=2,constrained_layout=True),代碼中ncols,nrows 表示的都是要定義的列行數,constrained_layout 的使用效果類似於plt.tight_layout()。
(4)圖中圖設置
在某些情況下,我們需要對圖中的細節進行放大,一般我們通過在圖中進行繪制另一個小圖,即圖中圖的模式,接下來將對圖中圖的格式及內容進行簡單的介紹:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
fig = plt.figure()
x = [1,2,3,4,5,6,7]
y = [1,3,4,2,5,8,6]
left,bottom,width,height = .1,.1,.8,.8
ax_1 = fig.add_axes([left,bottom,width,height])
ax_1.plot(x,y,'r')
ax_1.set_xlabel('x')
ax_1.set_ylabel('y')
ax_1.set_title('title')
left,bottom,width,height = .2,.6,.25,.25
ax_2 = fig.add_axes([left,bottom,width,height])
ax_2.plot(x,y,'b')
ax_2.set_xlabel('x')
ax_2.set_ylabel('y')
ax_2.set_title('title inside_1')
plt.axes([0.6,0.2,0.25,0.25])
plt.plot(y[::-1],x,'g')
plt.xlabel('x')
plt.ylabel('y')
plt.title('title inside_2')
plt.show()
通過觀察代碼發現,設置圖中圖的格式很簡單,跟繪圖時的情況一樣,其中主要通過fig.add_axes([left,bottom,width,height]) 來實現:
- fig.add_axes() 如字面意所示,增加坐標軸線,內部參數 [left,bottom,width,height] 表示距離整個圖框邊緣的比例,如 left=0.1 表示整個圖框從左向右的百分之10的位置繪制左框線,然后在 width=0.8 位置繪制右框線,同理bottom 和 height。
- 另外 (y[::-1],x) 表示x數據正序,而y數據降序。
2.3 Matplotlib繪圖樣式
2.3.1 2D圖形
Matplotlib中具有多種繪圖樣式,2D圖中除了折線圖外,還有2D的有散點圖、直方圖、等高線圖以及3D圖等,接下來將對Matplotlib中常用的圖形樣式進行簡單的講解。
(1) 散點圖
前面進行過簡單的散點圖的應用,但未就散點圖作為整個專題進行講述,接下來將針對散點圖的基本應用做簡要講述:
import matplotlib.pyplot as plt
import numpy as np
n = 1024
X = np.random.normal(0,1,n)
Y = np.random.normal(0,1,n)
T = np.arctan2(Y,X) # for color value
# plt.scatter(X,Y,s=75,c=T,alpha=0.5)
plt.scatter(np.arange(5),np.arange(5))
# plt.xlim((-1.5,1.5))
# plt.ylim((-1.5,1.5))
plt.xticks(())
plt.yticks(())
plt.show()
圖24和圖25分別由plt.scatter(X,Y,s=75,c=T,alpha=0.5) 和 plt.scatter(np.arange(5),np.arange(5)) 生成:
- 圖24中X,Y用到了np.random.normal(0,1,n),表示使用隨機正態分布,其中0為平均值,1為方差,n為生成點的個數,代碼中為1024;
- 另外T = np.arctan2(Y,X),該代碼是顏色生成函數,其作用是生成不同顏色的點,具體形式如圖24所示,點的顏色都呈現出不同的顏色。
- 針對圖25所生成的點中,用到了arange() 函數,該函數與range() 函數用法類似,但是arange() 函數生成的事列表,即在代碼中具體表現為$[1,2,3,4,5]$,而range() 函數生成的為單個的int 類型的整數。
(2) 柱狀圖
在眾多圖形中,柱狀圖是我們遇到的比較常見的圖形形式,方便我們對比觀察不同的數據量,接下來將對柱狀圖的繪制進行簡要概述:
import matplotlib.pyplot as plt
import numpy as np
n = 12
X = np.arange(n)
Y_1 = (1-X/float(n))*np.random.uniform(0.5,1.0,n)
Y_2 = (1-X/float(n))*np.random.uniform(0.5,1.0,n)
plt.bar(X,+Y_1,facecolor='#9999ff',edgecolor='white')
plt.bar(X,-Y_2,facecolor='#ff9999',edgecolor='white')
for x,y in zip(X,Y_1):
plt.text(x+0.04,y+0.05,'%.2f' %y,ha='center',va='bottom')
for x,y in zip(X,Y_2):
plt.text(x+0.04,-y-0.05,'-%.2f' %y,ha='center',va='top')
plt.xlim(-.5,n)
plt.xticks(()) # 坐標值去除替換
plt.ylim(-1.25,1.25)
plt.yticks(())
plt.show()
在代碼中,主要涉及到以下幾個方法:
-
np.random.uniform(0.5,1.0,n) 表示隨機均勻分布,0.5和1.0表示均勻分布的最小值和最大值,n表示生成的數據個數,代碼中為12個;為了方便生成浮點數,代碼中對Y值進行了float() 類型的相應轉換;
-
plt.bar(X,+Y_1,facecolor='#9999ff',edgecolor='white') 整個方法的理解可以參照基本繪圖方法plt.plot() 的類型理解,另外facecolor 表示柱狀圖內部填充顏色,顏色可使用的表示形式可查詢2.2.4節(1)部分的講解,edgecolor 表示柱狀圖外在框線的顏色;
-
在循環函數中:
for x,y in zip(X,Y_1): plt.text(x+0.04,y+0.05,'%.2f' %y,ha='center',va='bottom')zip() 方法為Python語言內置方法,可將(X,Y_1)轉換為元組打印。plt.text() 標注前2.2.3節講解過,此處不在進行詳細解釋,只針對內部參數進行講解:(x+0.04,y+0.05,'%.2f'\ %y,ha='center',va='bottom') 表示柱狀圖y軸數據相對坐標位置(x,y) 偏移量為(+0.04,+0.05) 的位置,又由於標注內容整體是個框形區域,依次可以進一步對對齊位置進行設置,代碼匯總設置為標注數據底部水平居中,其中ha 和 va 分別表示水平和豎直方向上的設置(格式可以參照Excel中的手動對齊樣式,可上下左右對齊);
-
代碼最后進行了坐標軸范圍及顯示設置即利用plt.xlim() 和 plt.xticks() 函數,又plt.xticks(()) 中括號內數據為空,所以坐標軸數據顯示無。
(3) 直方圖
在部分統計圖中,直方圖是一種比較重要的圖像,需要注意的事直方圖和前面的柱狀圖不同,需要區別對待,具體的區別可參考此處的博文,講的比較細致,方便大家理解:直方圖VS柱狀圖。接下來我們將進行簡單的直方圖的講解:
import numpy as np
import matplotlib.pyplot as plt
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
plt.hist(x, 50, density=1, facecolor='g', alpha=0.75)
plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title('Histogram of IQ')
plt.text(60, .025, r'$mu=100, sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True)
plt.show()
如代碼所示,代碼主要分為以下幾個部分:
-
np.random.randn() 是生成正態分布的函數,它具有以下幾個特性:
語法:
- 當函數括號內沒有參數時,則返回一個浮點數;
- 當函數括號內有一個參數時,則返回秩為1的數組,不能表示向量和矩陣;
- 當函數括號內有兩個及以上參數時,則返回對應維度的數組,能表示向量或矩陣;
- np.random.standard_normal()函數與np.random.randn()類似,但是np.random.standard_normal()的輸入參數為元組(tuple).
- np.random.randn()的輸入通常為整數,但是如果為浮點數,則會自動直接截斷轉換為整數。
作用:
返回一個或一組服從標准正態分布的隨機樣本值。
特點:
標准正態分布是以0為均數、以1為標准差的正態分布,記為N(0,1)。
因此np.random.randn(1000) 將隨機生成1000個服從標准正態分布的樣本值作為繪圖數據。
-
繪制直方圖,將利用方法plt.hist(x, 50, normed=1, facecolor='g', alpha=0.75),基於官方數據,hist 的參數主要有以下幾個:
matplotlib.pyplot.hist(x, bins=None, range=None, density=None, weights=None, cumulative=False, bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, color=None, label=None, stacked=False, normed=None, *, data=None, **kwargs) ''' ################################################# x: (n,) array or sequence of (n,) arrays 指定每個bin分布的數據,對應x軸 ################################################# bins: integer or array_like, optional 指定bin的個數,即共有幾條條狀圖 ################################################# density: boolean, optional,If `True`, the first element of the return tuple will be the counts normalized to form a probability density, i.e.,`n/(len(x)`dbin)` 指定密度,也就是每個條狀圖的占比例比,默認為1 ################################################# color: color or array_like of colors or None, optional ''' -
plt.grid(True) 中,當參數為False 時,圖27中網格線將消失.
(4) 等高線圖
在部分工程學科中,我們通常會使用到等高線的繪制,方便我們觀察整個圖中的地形地貌,因此接下來將對等高線的繪制進行簡要的概述:
import matplotlib.pyplot as plt
import numpy as np
def f(x,y):
# the height function
return (1-x/2+x**5+y**3)*np.exp(-x**2-y**2)
n = 256
x = np.linspace(-3,3,n)
y = np.linspace(-3,3,n)
X,Y = np.meshgrid(x,y)
# use plt.contourf to filling contours
# X,Y and value for (X,Y) point
plt.contourf(X,Y,f(X,Y),8,alpha=0.85,cmap=plt.cm.rainbow)
# use plt.contour to add contour lines
C = plt.contour(X,Y,f(X,Y),8,colors='black',linewidth=.2)
# adding label
plt.clabel(C,inline=True,fontsize=10)
plt.xticks(())
plt.yticks(())
plt.show()
代碼主要分為以下幾個部分:
-
(1)坐標數據網格化:等高線圖需要三維坐標數據,網格化的目的就是首先是建立平面網格化坐標(xy坐標系),然后再利用高度坐標進行網格數據升高,主要使用使用到的就是np.meshgrid() 方法,另外需要說明的是代碼中定義的函數目的是計算高度,沒有其他含義;
-
(2)等高線地圖設置:根據等高線數據plt.contourf(X,Y,f(X,Y),8,alpha=0.85,cmap=plt.cm.rainbow) 其中(X,Y,f(X,Y)) 是坐標數據,不進行解釋;方法中的8 表示從最小數據到最大數據將分成9條分界線,可以理解為[0,8]中共9個數據,分別將數據等分為 (9+1)個顏色區域進行顯示;參數cmap 表示圖像映射類型,代碼中使用了彩虹樣式(ranbow)進行展示,處理ranbow 外,還有以下映射方式進行展示:
Accent, Accent_r, Blues, Blues_r, BrBG, BrBG_r,BuGn, BuGn_r, BuPu, BuPu_r, CMRmap, CMRmap_r,Dark2, Dark2_r, GnBu, GnBu_r, Greens, Greens_r,Greys, Greys_r, OrRd, OrRd_r, Oranges, Oranges_r,PRGn, PRGn_r, Paired, Paired_r, Pastel1, Pastel1_r,Pastel2, Pastel2_r, PiYG, PiYG_r, PuBu, PuBuGn,PuBuGn_r, PuBu_r, PuOr, PuOr_r, PuRd, PuRd_r,Purples, Purples_r, RdBu, RdBu_r, RdGy, RdGy_r, RdPu,RdPu_r, RdYlBu, RdYlBu_r, RdYlGn, RdYlGn_r, Reds, Reds_r,Set1, Set1_r, Set2, Set2_r, Set3, Set3_r, Spectral,Spectral_r, Wistia, Wistia_r, YlGn, YlGnBu, YlGnBu_r,YlGn_r, YlOrBr, YlOrBr_r, YlOrRd, YlOrRd_r, afmhot,afmhot_r, autumn, autumn_r, binary, binary_r, bone,bone_r, brg, brg_r, bwr, bwr_r, cividis, cividis_r,cool, cool_r, coolwarm, coolwarm_r, copper, copper_r,cubehelix, cubehelix_r, flag, flag_r, gist_earth,gist_earth_r, gist_gray, gist_gray_r, gist_heat,gist_heat_r, gist_ncar, gist_ncar_r, gist_rainbow,gist_rainbow_r, gist_stern, gist_stern_r, gist_yarg,gist_yarg_r, gnuplot, gnuplot2, gnuplot2_r, gnuplot_r,gray, gray_r, hot, hot_r, hsv, hsv_r, inferno, inferno_r,jet, jet_r, magma, magma_r, nipy_spectral, nipy_spectral_r,ocean, ocean_r, pink, pink_r, plasma, plasma_r, prism, prism_r,rainbow, rainbow_r, seismic, seismic_r, spring, spring_r, summer,summer_r, tab10, tab10_r, tab20, tab20_r, tab20b, tab20b_r, tab20c,tab20c_r, terrain, terrain_r, twilight, twilight_r, twilight_shifted,twilight_shifted_r, viridis, viridis_r, winter, winter_r為方便觀察應用步驟,此處給出第二步下的生成圖,如圖28.1所示,通過圖可以發現,前兩步只給出了等高線背景圖,但是缺少等高線,這也是第三步所做內容。
圖 28.1 -
(3)等高線線型設置:基於圖28.1我們需要對不同區域的等高線進行邊界線的添加,主要用到C = plt.contour(X,Y,f(X,Y),8,colors='black',linewidth=.2),生成內容如圖28.2所示:
圖 28.2 -
(4)等高線標簽設置:基於圖28.2進行相應區域等高線數據的添加,主要涉及plt.clabel(C,inline=True,fontsize=10),clabel() 中的C 為前述生成等高線C的指代內容,因此生成結果如圖28所示,另外假如inline=False 則線會穿過標簽數據,如圖28.3所示,顯然不太美觀:
圖 28.3
(5) 數字圖像
有時我們會對部分數據進行圖像繪制,此處所指圖像是針對不同數據繪制不同區域以顯示的圖像,可能語言不直觀,接下來以具體實例進行示意講解:
import matplotlib.pyplot as plt
import numpy as np
# image data
a = np.array([0.313660827978,0.365348418405,0.423733120134,
0.365348418405,0.439599930621,0.525083754405, 0.423733120134,0.525083754405,0.651536351379]).reshape(3,3)
'''
for the value of 'interpolation',check this:
http:/matplotlib.org/examples/images_contours_and_fields/interpolation_methods.html
'''
plt.imshow(a,interpolation='nearest',cmap='bone',origin='upper')
plt.colorbar(shrink=.9)
plt.xticks(())
plt.yticks(())
plt.show()
上述代碼主要涉及以下幾個部分:
-
數據處理部分:在代碼中定義了一個列表,其包含9個數據,並利用reshape() 方法將(91)的列表(矩陣)轉換成了(33) 矩陣;
-
圖像繪制部分:將數據展示為圖片樣式涉及使用方法plt.imshow(a,interpolation='nearest',cmap='bone',origin='upper'),參數interpolation 展示方法有很多種,官網上給出了很多形式,具體網址為Matplotlib_interpolation,方法主要有:
None, 'none', 'nearest', 'bilinear', 'bicubic', 'spline16','spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric','catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos'參數cmap 是顏色映射形式,具體參考2.3.1節(4)等高線中的講解,此處不再贅述;參數origin 是處理數據大小排列問題,可以理解為降序或者升序。
-
圖像標簽設置:數據標簽展示涉及plt.colorbar(shrink=.9) 即圖像右側數據標簽,內部參數眾多,代碼中使用了shrink=0.9 即標簽高度是整個圖片圖像的90%。
(6) 餅狀圖
在我們統計數據時,餅狀圖能夠很方便我們對整體-部分之間關系的描述,接下來我們將對餅狀圖進行簡要概述:
import matplotlib.pyplot as plt
label = 'Frogs', 'Hogs', 'Dogs', 'Logs' # 設置標簽
sizes = [15, 30, 45, 10] # 占比,和為100
color = ['yellowgreen', 'gold', 'lightskyblue', 'lightcoral'] # 顏色
explode_ = (0, 0.1, 0, 0) # 展開第二個扇形,即Hogs,間距為0.1
plt.pie(sizes, explode=explode_, labels=label, colors=color, autopct='%1.1f%%', shadow=True,startangle=90)
# startangle控制餅狀圖的旋轉方向
plt.axis('equal') # 保證餅狀圖是正圓,否則會有一點角度偏斜
plt.show()
如代碼所示,餅狀圖代碼較為簡單,主要利用了plt.pie() 的方法進行繪制,其中常用的幾個參數如下:
-
sizes: 參數size主要定義了餅狀圖的數據分布,代碼定義了4個數據,和為100,這是正好的情況,假如4個數據和不等於100,則程序自動計算各個數據在占據整體的百分比。當size=[15, 40, 45, 10] 時,圖像如30.1所示:
圖 30.1 -
color: 參數color可以根據顏色全稱定義,也可以根據顏色16進制定義顏色;
-
label: 參數label定義區域名稱;
-
explode: 參數explode定義部分區域偏移距離,如圖30.1,代碼中這對Hogs 進行偏移,偏移距離為0.1;
-
autopct: 扇形區域數據表示格式,控制輸出格式內容與print() 控制輸出數據格式長度及保留位數方法相同;
-
shadow: 是否顯示陰影,圖30為顯示shadow,圖30.2為不顯示shadow:
圖 30.2 -
startangle: 表示餅狀圖以x軸為基准軸逆時針旋轉角度,官方定義為:
If not None, rotates the start of the pie chart by angle degrees counterclockwise from the x-axis
圖30.3為旋轉45度后的圖形:
圖 30.3
另外除了上述參數外,plt.pie()還有其他參數,具體請參看官網Matplotlib_pie,同時需要注意,上述參數中的數據一一對應,所以繪制是務必重視。
(7) 玫瑰圖
在部分領域,如氣象等常使用風向玫瑰圖進行統計數據展示,玫瑰圖實際是一種2維極坐標統計圖,以動徑和動徑角表示制圖對象按方位、時間或多項指標的統計數據,有很好的直觀效果。接下來我們將對玫瑰圖的繪制做簡要概述:
import numpy as np
import matplotlib.pyplot as plt
N = 20
theta = np.linspace(0.0, 2 * np.pi, N, endpoint=False)
radii = 10 * np.random.rand(N)
width_ = np.pi / 4 * np.random.rand(N)
# 驗證
# print(theta*/np.pi,radii,width)
ax = plt.subplot(111, projection='polar')
bars = ax.bar(theta, radii, width=width_, bottom=0.0)
# Use custom colors and opacity
for r, bar in zip(radii, bars):
bar.set_facecolor(plt.cm.jet(r / 10.))
bar.set_alpha(0.5)
plt.show()
如代碼所示,玫瑰圖基於極坐標圖繪制,觀察代碼,主要涉及以下幾個部分:
-
(1)數據處理:np.linspace() 的參數定義為:
linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None),基於參數定義,代碼中的最后一個數值將不被利用。
start: scalar
隊列的開始值
stop: scalar
隊列的結束值。當‘endpoint=False’時,不包含該點。在這種情況下,隊列包含除了“num+1"以外的所有等間距的樣本,要注意的是,當‘endpoint=False’時,步長會發生改變。
num: int, optional
要生成的樣本數。默認是50,必須要非負。
endpoint: bool, optional
如果是True,’stop'是最后的樣本。否則,'stop'將不會被包含。默認為true
retstep: bool, optional
If True, return (
samples,step), wherestepis the spacing between samples. -
(2)極坐標繪制:ax = plt.subplot(111, projection='polar') 代碼利用參數projection 進行極坐標的啟用,實際上ax = plt.subplot(111, polar=True) 這樣寫也是可以的,polar=True 等價於projection='polar',另外projection='rectilinear' 為默認設置,即為直角坐標系,具體參數可參加官網 matplotlib_projections。生成圖形如圖31.1所示:
圖 31.1 -
(3)玫瑰花瓣繪制:基於數據和極坐標系,利用bars = ax.bar(theta, radii, width=width_, bottom=0.0) 進行玫瑰花瓣的繪制,其中(theta, radii, width) 分別為花瓣角度,半徑和花瓣高度,theta即每個花瓣對稱軸位置與0度所成角度;radii 即為花瓣半徑,width 即為花瓣外延側長度,可以理解弧長的長度;需要注意的是theta 並非花瓣兩條半徑之間的角度,而是花瓣對稱軸與0度 軸線所成角度;另外可通過修改三個參數內的數字並打印然后並對比圖像可驗證三個參數的具體含義(代碼中注釋為驗證的位置)。bottom 是設置花瓣內沿側寬度,觀察圖31.2即可明白,通過將bottom 增加為10,則可獲得。另外需要強調,由於花瓣數據隨機生成,所以每次上述的(theta, radii, width) 會有所不同:
圖 31.2 -
(4)玫瑰花瓣上色:代碼中通過循環語句相應操作進行不同花色的顯示:
for r, bar in zip(radii, bars): bar.set_facecolor(plt.cm.jet(r / 10.)) bar.set_alpha(0.5)代碼中主要說明兩點,
a. 循環參數中r 不是固定的,也可用width_ 進行處理,但是由於width_數值變化小,所以會造成花瓣整體色差不明顯,因此用r 效果更好些,但是bar 是必須存在,不可替換,因為着色對象即為bar。
b. 在花瓣內部着色中用到了plt.cm.jet(),關於jet,官方給出的定義是:
Set the colormap to "jet".This changes the default colormap as well as the colormap of the current image if there is one.
代碼中的jet可參照等高線圖中給出的色表,其效果等同於rainbow等。
2.3.2 3D圖形
Matplotlib雖然是2D圖像庫,但是仍能夠簡單繪制部分3D圖像,接下來將對3D圖像的簡單繪制進行介紹:
(1) 散點圖
首先進行3D散點圖的講解,相對來說3D散點圖應用較少,但其仍是一種很重要的3D數據表現形式,因此接下來將對其進行簡要講解:
# 3維散點圖
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
# x, y, z 均為 0 到 1 之間的 100 個隨機數
x = np.random.normal(0, 1, 100)
y = np.random.normal(0, 1, 100)
z = np.random.normal(0, 1, 100)
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(x, y, z)
plt.show()
繪制3D圖前首先要導入mpl_toolkits.mplot3d.Axes3D 圖形庫,但同時仍需要使用pyplot 模塊,因為Matplotlib 繪制三維圖像實際上是在二維畫布上展示。mplot3d 模塊下主要包含 5 個大類,分別為axes3d、axis3d、art3d、Art3D Utility Functions 和 proj3d,其中最常用的就是axes3d,其他詳細情況請參見官網:Mplot3d_API。
代碼內容很簡單,主要用到的方法為ax = Axes3D(),即添加三維坐標軸,具體如圖32.1所示,然后依據(x,y,z) 坐標繪制散點圖即可得到圖32所示圖形。
(2) 曲線圖
接下來進行3D曲線圖的講解,同樣作為3D繪圖形式必不可少的繪圖形式,接下來將對3D曲線圖進行簡要概述:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
# 生成數據
x = np.linspace(-6 * np.pi, 6 * np.pi, 1000)
y = np.sin(x)
z = np.cos(x)
# 創建 3D 圖形對象
fig = plt.figure()
ax = Axes3D(fig)
ax.plot(x, y, z)
plt.show()
代碼整體形式與三維散點圖代碼類似,因此在此不再做過多贅述,主要還是利用ax = Axes3D() 繪制出坐標軸后進行三維數據的添加繪制。
(3) 柱狀圖
通過三維柱狀圖可以多維度的反映數據變化,比二維柱狀圖更加形象,接下來將對其進行簡單概述:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
# 創建 3D 圖形對象
fig = plt.figure()
ax = Axes3D(fig)
# 生成數據並繪圖
x = [0, 1, 2, 3, 4, 5, 6]
for i in x:
y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
z = abs(np.random.normal(1, 10, 10))
ax.bar(y, z, i, zdir='y', color=['r', 'g', 'b', 'y'])
plt.show()
此處主要進行下兩部分內容的講解:
-
zdir() 表示向某方向投影的函數,代碼中函數參數為y,即將3維柱狀圖轉換為2維柱狀圖視角的話,整個柱面基於y軸,同理通過修改參數,將其改為x,則圖形顯示為圖31.1所示結果:
圖 34.1 -
在循環語句中,確定z軸顏色時,代碼給出了color=['r', 'g', 'b', 'y'] 四種顏色,其實這個沒有數量固定,也可以給一種顏色,也可以給多於4種的顏色,以下是只給出紅色的情況下結果的顯示:
圖 34.2
(4) 線框圖
線框圖是曲面圖中網格線的圖像,以下將對其進行簡要概述:
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(1, 1, 1, projection='3d')
ax = Axes3D(fig)
x = np.arange(-4,4,0.25)
y = np.arange(-4,4,0.25)
X,Y = np.meshgrid(x,y)
R = np.sqrt(X**2+Y**2)
# height value
Z = np.sin(R)
# rstride和cstride分別為網格下的行跨和列跨
ax.plot_wireframe(X, Y, Z, rstride=1, cstride=1)
plt.show()
此處重點對ax.plot_wireframe(X, Y, Z, rstride=1, cstride=1) 進行解說,繪制線框圖需要利用ax.wireframe() 的方法,該方法的參數較多,具體可查看官網說明:plot_wireframe,此處重點進行內部參數rstride 和 cstride 的解釋。參數rstride 和 cstride 分別為網格下的行跨和列跨,兩參數需是正整數(為負整數時,圖像消失;為小數時,程序出錯),且密度與數字成反比,也就是說當 (rstride=1, cstride=1) 時,網格最密,以下是修改網格,使 (rstride=3, cstride=3) 的情形:
(5) 曲面圖
曲面圖(Surface Plot)是3D圖像中常用的形式,接下來將對3D曲面圖進行簡要講解:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = Axes3D(fig)
# X,Y value
X = np.arange(-4,4,0.25)
Y = np.arange(-4,4,0.25)
X,Y = np.meshgrid(X,Y)
R = np.sqrt(X**2+Y**2)
# height value
Z = np.sin(R)
# rstride和cstride分別為網格下的行跨和列跨
ax.plot_surface(X,Y,Z,rstride=1,cstride=1,cmap=plt.get_cmap('rainbow'))
# zdir是三維圖投影方向的方法
ax.contourf(X,Y,Z,zdir='z',offset=-2,cmap='rainbow')
ax.set_zlim(-2,2)
plt.show()
針對代碼主要介紹三個內容:
-
ax.set_zlim(-2,2): 設置z軸范圍,即效果同xlim() 和 ylim() 作用相同;
-
ax.plot_surface(): 即繪制三維曲面圖函數ax.plot_surface(),其中,cmap=plt.get_cmap('rainbow') 等價於cmap=plt.cm.rainbow 和 cmap=‘rainbow’,其余內部參數前面已做講述,不再贅述。
-
ax.contourf(): 設置投影等高線圖,實質上contour 和contourf 都能進行等高線投影圖的設置,不過contour 不同區域間未進行填充,而contourf 區域內部進行了填充,將代碼中的contourf 修改為 contour 則可得圖36.1所示圖形:
圖 36.1
2.3.3 動圖繪制
在部分場合我們需要觀察一段時期內圖形的數據變化,相對於靜圖,動態在該種場合下優勢就比較明顯,因此接下來將對動圖的設置進行簡要介紹:
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np
fig,ax = plt.subplots()
x = np.arange(0,2*np.pi,0.01)
line, = ax.plot(x,np.sin(x))
def animate(i):
line.set_ydata(np.sin(x+i/10))
return line,
def init():
line.set_ydata(np.sin(x))
return line,
# 圖像元素全部更改blit=False,變化元素更改blit=True
ani = animation.FuncAnimation(fig=fig,func=animate,frames=100,init_func=init,interval=100,blit=False)
# 保存GIF格式
ani.save('st_.gif',writer='imagemagick')
plt.show()
使用動圖需要導入animation 模塊,基於官方定義,詳細請參見Animation:
The easiest way to make a live animation in matplotlib is to use one of the
Animationclasses.(1)
FuncAnimation—— Makes an animation by repeatedly calling a functionfunc.(2)
ArtistAnimation—— Animation using a fixed set ofArtistobjects.
上述代碼主要涉及以下幾個關鍵函數和方法:
-
animation.FuncAnimation: 設置動圖需要使用方法FuncAnimation,其中定義了幾個關鍵參數:
(1)fig: 設置動圖的圖形界面;
(2)func: 設置動圖變化的函數;
(3)frames: 設置動圖幀數,即可以看做圖像更新次數,其中圖37.1表示幀數為10,由於幀數未形成一個周期,所以相對於圖37來說顯得有點斷斷續續:
圖 37.1 (4)init_func: 函數最初形式,即動畫第一幀的函數圖像;
(5)interval: 設置動畫更新間隔時間;其中圖37.2表示間隔為500,由於間隔時間較長,所以圖37.2顯得有點遲鈍,圖37.3表示間隔為20,相較於圖37和圖37.2,圖37.3變化速度要快很多,但是需要注意點,由於幀數不合適,所以在速度較快的情況下,顯示出與圖37.1類似的情況,因此interval 和 frame 要選擇恰當:
圖 37.2
圖 37.3 (6)blit: 設置圖像元素更新對象,blit=False時,圖像元素全部更新,blit=True,表示產生變化的元素更改(不變化的元素不更新)
-
在animate(i) 中,需要傳入變化值,此處為 i ,取值范圍為[0,frames];
-
line,:由於plot 返回值為列表,line, 作為列表的第一個值,需要添加,,同理在函數init() 中的表示。
最后需要說明的是,Matplotlib並沒有內置的GIF導出模塊,需要借助第三方工具,此處給出設置詳細步驟及下載工具界面,請參見網址Matplotlib2Gif。
