一、實驗介紹
1.1 實驗內容
Matplotlib 是支持 Python 語言的開源繪圖庫,因爲其支持豐富的繪圖類型、簡單的繪圖方式以及完善的接口文檔,深受 Python 工程師、科研學者、數據工程師等各類人士的喜歡。這是 Matplotlib 繪圖課程的第 2 章節,將帶你學會如何使用參數繪出更復雜的 2D 圖像。
1.2 實驗知識點
- Matplotlib 繪製 2D 圖像
1.3 實驗環境
- python2.7
- Xfce 終端
- ipython 終端
1.4 適合人羣
本課程難度爲一般,屬於初級級別課程,適合具有 Python 基礎,並對使用 Matplotlib 繪圖感興趣的用戶。
二、二維繪圖進階
在前一個章節中,我們已經瞭解到瞭如何使用 Matplotlib 繪出常用的圖像,包括線型圖、餅狀圖、散點圖等。但是,Matplotlib 默認的樣式的確算不上美觀。所以,這一個章節就是如何設置繪圖方法的參數,從而畫出更漂亮和自己想要的圖形。
2.1 線型圖樣式
我們已經知道了,線型圖通過 matplotlib.pyplot.plot(*args, **kwargs)
方法繪出。其中,args
代表數據輸入,而 kwargs
的部分就是用於設置樣式參數了。
二維線型圖包含的參數超過 40 餘項(文檔 P1390)。其中常用的也有 10 餘項,選取一些比較有代表性的參數列舉如下:
參數 | 含義 |
---|---|
alpha= |
設置線型的透明度,從 0.0 到 1.0 |
color= |
設置線型的顏色 |
fillstyle= |
設置線型的填充樣式 |
linestyle= |
設置線型的樣式 |
linewidth= |
設置線型的寬度 |
marker= |
設置標記點的樣式 |
…… | …… |
對於上面提到的這幾項。
線型顏色 color =
的預設值(文檔 P1527)有:
color = 參數值 |
顏色 |
---|---|
b | 藍色 |
g | 綠色 |
r | 紅色 |
w | 白色 |
m | 洋紅色 |
y | 黃色 |
k | 黑色 |
…… | …… |
其實,大部分都是所顏色所對應的英文名稱首字母。當然,你也可以通過color = '#008000'
的方式來設置任何你想要的顏色。
線型的樣式 linestyle =
預設的參數值(文檔 P1250)有:
linestyle = 參數值 |
線型 |
---|---|
'-' | 默認實線 |
'--' | 虛線 |
'-.' | 間斷線 |
':' | 點狀線 |
下圖展示了 4 種常見線型的樣式
樣本點標記樣式 marker =
預設的參數值(文檔 P1527)就更多了:
marker = 參數值 |
樣本點標記 |
---|---|
'.' | 實心點 |
',' | 像素點 |
'o' | 空心點 |
'p' | 五角形 |
'x' | x 形 |
'+' | + 形 |
…… | …… |
下圖展示了所有標記對應的參數值和樣式
下面,我們來重新畫一遍正弦函數的圖像。添加幾個參數,希望它不再那麼單調。由於在線環境的 Matplotlib 版本較低,在本地環境運行的最新版本畫出來的默認圖像樣式會更好看一些。
# -*- coding: utf-8 -*
from matplotlib import pyplot as plt # 載入 pyplot 繪圖模塊
import numpy as np # 載入數值計算模塊
# 在 -2PI 和 2PI 之間等間距生成 1000 個值,也就是 X 座標
X = np.linspace(-2 * np.pi, 2 * np.pi, 1000)
# 計算 sin() 對應的縱座標
y1 = np.sin(X)
# 計算 cos() 對應的縱座標
y2 = np.cos(X)
# 向方法中 `*args` 輸入 X,y 座標
plt.plot(X, y1, color='r', linestyle='--', linewidth=2, alpha=0.8)
plt.plot(X, y2, color='b', linestyle='-', linewidth=2)
plt.show()
2.2 散點圖樣式
除了線型圖以外,散點圖也是常用圖形之一。例如,我們在使用機器學習算法聚類的時候,往往就會通過散點圖將樣本數據展示出來。
Matplotlib 中,繪製散點圖的方法我們已經知道了,那就是 matplotlib.pyplot.scatter()
。接下來,我們就看一看它包含有哪些參數。
參數 | 含義 |
---|---|
s= |
散點大小 |
c= |
散點顏色 |
marker= |
散點樣式 |
cmap= |
定義多類別散點的顏色 |
alpha= |
點的透明度 |
edgecolors= |
散點邊緣顏色 |
其中,散點的大小通過設置數值大小控制。散點的顏色可以是一種,參數值和線型的顏色設置類似。散點的顏色也可以是多種,可以使用一個列表對每一個點的顏色單獨設置。
# -*- coding: utf-8 -*
from matplotlib import pyplot as plt # 載入 pyplot 繪圖模塊
import numpy as np # 載入數值計算模塊
x = np.random.rand(100) # 隨機在 0 到 1 之間生成 100 個數值
y = np.random.rand(100) # 隨機在 0 到 1 之間生成 100 個數值
colors = np.random.rand(100) # 隨機在 0 到 1 之間生成 100 個數值
size = np.random.normal(20, 30, 100) # 隨機在 20 到 30 之間生成 100 個數值
# 繪製散點圖
plt.scatter(x, y, s=size, c=colors)
plt.show()
2.3 餅狀圖樣式
餅狀圖通過 matplotlib.pyplot.pie()
繪出。我們也可以進一步設置它的顏色、標籤、陰影等各類樣式。下面就繪出一個示例。
# -*- coding: utf-8 -*
import matplotlib.pyplot as plt
label = 'Cat', 'Dog', 'Cattle', 'Sheep', 'Horse' # 各類別標籤
color = 'r', 'g', 'r', 'g', 'y' # 各類別顏色
size = [1, 2, 3, 4, 5] # 各類別佔比
explode = (0, 0, 0, 0, 0.2) # 各類別的偏移半徑
# 繪製餅狀圖
plt.pie(size, colors=color, explode=explode, labels=label, shadow=True, autopct='%1.1f%%')
# 餅狀圖呈正圓
plt.axis('equal')
# 顯示圖
plt.show()
2.4 組合圖
上面演示了三種常見圖像的繪製。實際上,我們往往會遇到將幾種類型的一樣的圖放在一張圖內顯示,也就是組合圖的繪製。
其實很簡單,你只需要將需要或者的組合圖樣式放在一起就好了,比如柱形圖和折線圖。
# -*- coding: utf-8 -*
import matplotlib.pyplot as plt
x = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
y_bar = [3, 4, 6, 8, 9, 10, 9, 11, 7, 8]
y_line = [2, 3, 5, 7, 8, 9, 8, 10, 6, 7]
plt.bar(x, y_bar)
plt.plot(x, y_line, '-o', color='y')
plt.show()
2.5 子圖繪製
上面提到了組合圖繪製,但有一些圖是無法組合直接放在一起的,這時就需要子圖了。子圖,就是將幾張獨立的圖放在一張大圖中呈現。在一些需要對比的情形下,子圖非常有效。
Matplotlib 中,繪製子圖的方法爲matplotlib.pyplot.subplot()
,我們通過該方法來控制各子圖的顯示順序。其中:
subplot(行序號, 列序號, 圖序號)
下面列舉了三種常見子圖的位置關係示意圖。
接下來,我們繪製了一個由 4 個子圖(2 行 x 2 列)組成的大圖。
import numpy as np
import matplotlib.pyplot as plt
# 生成數據
x = np.linspace(-2*np.pi, 2*np.pi)
y1 = np.sin(x)
y2 = np.cos(x)
# 子圖 1
plt.subplot(2, 2, 1)
plt.plot(x, y1, 'k')
# 子圖 2
plt.subplot(2, 2, 2)
plt.plot(x, y2, 'r')
# 子圖 3
plt.subplot(2, 2, 3)
plt.plot(x, y2, 'y')
# 子圖 4
plt.subplot(2, 2, 4)
plt.plot(x, y2, 'g')
plt.show()
除了這類平行或垂直排列的子圖,我們還可以通過 matplotlib.pyplot.subplot()
繪製出更復雜的樣式。比如,大圖套小圖。
import numpy as np
import matplotlib.pyplot as plt
# 生成數據
x = np.linspace(-2 * np.pi, 2 * np.pi)
y1 = np.sin(x)
y2 = np.cos(x)
# 大圖
plt.axes([.1, .1, .8, .8])
plt.plot(x, y1, 'k')
# 小圖
plt.axes([.6, .6, .3, .3])
plt.plot(x, y2, 'r')
plt.show()
2.6 繪製圖例
一般情況下,當繪製好圖案後,還需要繪製圖例。Matplotlib 中,圖例可以通過 matplotlib.pyplot.legend()
方法繪製。我們又拿上面的正弦和餘弦曲線舉例。
# -*- coding: utf-8 -*
from matplotlib import pyplot as plt # 載入 pyplot 繪圖模塊
import numpy as np # 載入數值計算模塊
# 生成數據
X = np.linspace(-2 * np.pi, 2 * np.pi, 1000)
y1 = np.sin(X)
y2 = np.cos(X)
# 使用 label= 添加標籤
plt.plot(X, y1, color='r', linestyle='--', linewidth=2, label='sin 函數')
plt.plot(X, y2, color='b', linestyle='-', linewidth=2, label='cos 函數')
# 繪製圖例
plt.legend(loc='upper left')
plt.show()
在這裏,我們需要修改兩個地方,也就是通過 label=
爲每一條曲線添加標籤。然後,增加一條 plt.legend(loc='upper
left')
就可以了。其中,loc='upper left'
是指明圖例的位置,例如這裏是左上方。你還可以通過 down
和 right
組合實現位置的變換。
上方繪製出來的最終圖像如下所示:
當然,這只是圖例中的樣式之一。你可以瀏覽官方文檔 1237 頁查看其他樣式的繪製方法。
2.7 圖像標註
當我們繪製一些較爲複雜的圖像時,閱讀對象往往很難全面理解圖像的含義。而此時,圖像標註往往會起到畫龍點睛的效果。圖像標註,就是在畫面上添加文字註釋、指示箭頭、圖框等各類標註元素。
Matplotlib 中,文字標註的方法由 matplotlib.pyplot.text()
實現。最基本的樣式爲 matplotlib.pyplot.text(x,
y, s)
,其中 x, y 用於標註位置定位,s 代表標註的字符串。除此之外,你還可以通過 fontsize=
, horizontalalignment=
等參數調整標註字體的大小,對齊樣式等。
下面,我們舉一個對柱形圖進行文字標註的示例。
# -*- coding: utf-8 -*
from matplotlib import pyplot as plt # 載入繪圖模塊
x_bar = [10, 20, 30, 40, 50] #柱形圖橫座標
y_bar = [0.5, 0.6, 0.7, 0.4, 0.6] #柱形圖縱座標
bars = plt.bar(x_bar, y_bar, color='blue', label=x_bar, width=2) # 繪製柱形圖
for i, rect in enumerate(bars):
x_text = rect.get_x() # 獲取柱形圖橫座標
y_text = rect.get_height() + 0.01 # 獲取柱子的高度並增加 0.01
plt.text(x_text, y_text, '%.1f' % y_bar[i]) # 標註文字
plt.show()
除了文字標註之外,還可以通過 matplotlib.pyplot.annotate()
方法向圖像中添加箭頭等樣式標註。接下來,我們向上面的例子中增添一行增加箭頭標記的代碼。
# -*- coding: utf-8 -*
from matplotlib import pyplot as plt # 載入繪圖模塊
x_bar = [10, 20, 30, 40, 50] #柱形圖橫座標
y_bar = [0.5, 0.6, 0.7, 0.4, 0.6] #柱形圖縱座標
bars = plt.bar(x_bar, y_bar, color='blue', label=x_bar, width=2) # 繪製柱形圖
for i, rect in enumerate(bars):
x_text = rect.get_x() # 獲取柱形圖橫座標
y_text = rect.get_height() + 0.01 # 獲取柱子的高度並增加 0.01
plt.text(x_text, y_text, '%.1f' % y_bar[i]) # 標註文字
# 增加箭頭標註
plt.annotate('Max', xy=(32, 0.6), xytext=(38, 0.6), arrowprops=dict(facecolor='black', width=1, headwidth=7))
plt.show()
上面的示例中,xy=()
表示標註終點座標,xytext=()
表示標註起點座標。另外,arrowprops=()
用於設置箭頭樣式,facecolor=
設置顏色,width=
設置箭尾寬度,headwidth=
設置箭頭寬度。
在箭頭繪製的過程中,還有一個 arrowstyle=
用於改變箭頭的樣式。下圖展示了常見的箭頭樣式。
另外,connectionstyle=
的參數可以用於更改箭頭連接的樣式。下圖展示了常見的箭頭連接樣式。
2.8 動態圖繪製
動態圖是繪圖中不可缺少的一部分,雖然演示環境要求高且使用頻率低,但在一些特定的場景下,動圖傳達的信息量遠大於靜態圖片。
舉個例子來講,數值計算中,我們往往會使用到梯度下降法。如果用語言和公式描述梯度下降的過程,會非常枯燥。要是通過繪製一張演示梯度下降過程的動圖,就算第一次接觸該方法,也會很快的理解。
Matplotlib 很早開始就支持動態圖了,下面就通過簡單的小例子來演示一下動態圖的繪製。
動態圖主要是通過 animation 模塊實現。具體就是 matplotlib.animation.FuncAnimation(fig, func)
。其中,fig
代表所繪製的圖像。而 func 可以看作是更新函數,它刷新每一幀的值。
# -*- coding: utf-8 -*
# 載入模塊
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
# 生成數據並建立繪製類型的圖像
fig, ax = plt.subplots()
x = np.arange(0, 2 * np.pi, 0.01)
line, = plt.plot(x, np.sin(x))
# 更新函數
def update(i):
line.set_ydata(np.sin(x + i / 10.0))
return line,
# 繪製動圖
animation = animation.FuncAnimation(fig, update)
# 顯示圖
plt.show()
三、實驗總結
本次實驗對 2D 繪圖中,常見方法包含的參數進行的熟悉,方便繪製出樣式更爲複雜的圖像。當然,這些內容依舊較爲初級,可能無法完全滿足實際需要。而真正的繪圖過程中,我們需要從實際需求出發,善於組合 Matplotlib 中提供的繪圖方法,從而畫出更加漂亮的圖像。
四、課後習題
1.親自動手,嘗試通過 Matplotlib 繪製出下圖這副圖像。
上圖參考代碼:
$ wget http://labfile.oss.aliyuncs.com/courses/892/sin_cos_functions.py