Photo by MontyLov on Unsplash
上篇文章,我們了解到 Matplotlib 是一個風格類似 Matlab 的基於 Python 的繪圖庫。它提供了一整套和matlab相似的命令API,十分適合交互式地進行製圖。而且我們也可以方便地將它作為繪圖控制項,嵌入GUI應用程式中。本文主要走進 Matplotlib 的世界,初步學會繪製圖形。
在學習繪製之前,先來了解下 Matplotlib 基礎概念。
我們繪製圖形主要用到兩個庫,matplotlib.pyplot 和 numpy。在編碼過程中,這兩個庫的使用頻率較高,而這兩個庫的名字較長。這難免會給我們帶來不便。所以我們一般給其設置別名, 大大減少重複性工作量。具體如下代碼:
import matplotlib.pyplot as plt
import numpy as np
numpy 是 Python 用於數學運算的庫,它是在安裝 matplotlib 時候順帶安裝的。pyplot 是 matplotlib 一個子模塊,主要為底層的面向對象的繪圖庫提供狀態機界面。狀態機隱式地自動創建數字和坐標軸以實現所需的繪圖。 matplotlib 中的所有內容都按照層次結果進行組織。頂層就是由 pyplot 提供的 matplotlib 「狀態機環境」。基於這個狀態機環境,我們就可以創建圖形。
我在 matplotlib 官網上找圖像組件說明圖並在上面增加中文翻譯。通過這張圖,我們對 matplotlib 整體地認識。
接下來,我主要講解 matplotlib 中幾個重要的標籤。
Figure 翻譯成中文是圖像窗口。Figure 是包裹 Axes、tiles、legends 等組件的最外層窗口。它其實是一個 Windows 應用窗口 。
Figure 中最主要的元素是 Axes(子圖)。一個 Figure 中可以有多個子圖,但至少要有一個能夠顯示內容的子圖。
Axes 翻譯成中文是軸域/子圖。Axes 是帶有數據的圖像區域。從上文可知,它是位於 Figure 裡面。那它和 Figure 是什麼關係?這裡可能文字難以表述清楚,我以圖說文。用兩圖帶你徹底弄清它們的關係。
在看運行結果之前,我先呈上代碼給各位看官品嘗。
fig = plt.figure()
fig.suptitle('No axes on this figure')
fig, ax_lst = plt.subplots(2, 2)
plt.show()
根據運行結果圖,我們不難看出。左圖的 Figure1 中沒有 axes,右圖的 Figure2 中有 4 個 axes。因此,我們可以將 Axes 理解為面板,而面板是覆在窗口(Figure) 上。
Axis 在中文的意思是軸。官網文檔對 Axis 定義解釋不清楚,讓我們看得雲裡霧裡的。如果你有留意前文的組成說明圖,可以看到 X Axis 和 Y Axis 的字樣。按照平常人的見識, 觀察該圖就能明白 Axis 是軸的意思。此外,Axis 和 Axes 以及 Figure 這三者關係,你看完下圖,會恍然大悟。
按照劇本發展,我接下來以繪製曲線並逐步美化它為例子,一步步講解如何繪製圖形。在這過程中,我也會逐一說明各個函數的作用。
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-2, 6, 50)
y1 = x + 3
y2 = 3 - x
plt.figure()
plt.plot(x, y1)
plt.plot(x, y2)
plt.show()
調用 np.linspace 是創建一個 numpy 數組,並記作 x。x 包含了從 -2 到 6 之間等間隔的 50 個值。y1 和 y2 則分別是這 50 個值對應曲線的函數值組成的 numpy 數組。前面的操作還處於設置屬性的階段,還沒有開始繪製圖形。plt.figure() 函數才意味著開始執行繪圖操作。最後別忘記調用 show() 函數將圖形呈現出來。
我們已經繪製出兩條直線,但樣式比較簡陋。所以我給兩條曲線設置鮮豔的顏色、線條類型。同時,還給縱軸和橫軸的設置上下限,增加可觀性。
import matplotlib.pyplot as plt
import numpy as np
plt.figure(figsize=(8, 6), dpi=80)
plt.subplot(111)
x = np.linspace(-2, 6, 50)
y1 = x + 3
y2 = 3 - x
plt.plot(x, y1, color="blue", linewidth=1.0, linestyle="-")
plt.plot(x, y2, color="#800080", linewidth=2.0, linestyle="--")
plt.xlim(-1, 6)
plt.ylim(-2, 10)
plt.show()
在圖像中,我們不能一味地認為橫軸就是 X 軸,縱軸就是 Y 軸。圖形因內容數據不同,縱橫軸標籤往往也會不同。這也體現了給縱橫軸設置標籤說明的重要性。
...
# 設置橫軸標籤
plt.xlabel("X")
# 設置縱軸標籤
plt.ylabel("Y")
plt.show()
matplotlib 畫圖設置的刻度是由曲線以及窗口的像素點等因素決定。這些刻度精確度無法滿足需求,我們需要手動添加刻度。上圖中,縱軸只顯示 2 的倍數的刻度,橫軸只顯示 1 的倍數的刻度。我們為其添加精準刻度,縱軸變成單位間隔為 1 的刻度,橫軸變成單位間隔為 0.5 的刻度。
...
plt.xticks([-1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5])
plt.yticks([-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
plt.show()
xticks() 和 yticks() 需要傳入一個列表作為參數。
該方法默認是將列表的值來設置刻度標籤,如果你想重新設置刻度標籤,則需要傳入兩個列表參數給 xticks() 和 yticks() 。第一個列表的值代表刻度,第二個列表的值代表刻度所顯示的標籤。
...
plt.xticks([-1, 0, 1, 2, 3, 4, 5, 6],
["-1m", "0m", "1m", "2m", "3m", "4m", "5m", "6m"])
plt.yticks([-2, 0, 2, 4, 6, 8, 10],
["-2m", "0m", "2m", "4m", "6m", "8m", "10m"])
plt.show()
如果需要在圖的左上角添加一個圖例。我們只需要在 plot() 函數裡以「鍵 - 值」的形式增加一個參數。首先我們需要在繪製曲線的時候,增加一個 label 參數,然後再調用 plt.legend() 繪製出一個圖例。plt.legend() 需要傳入一個位置值。loc 的值可選如下:
值說明best自動選擇最佳位置,默認是左上upper right右上upper left左上lower right右下lower left左下right右邊,默認是右上。如果因圖形擋住右上,會自動往下選擇空白地方繪製center right垂直居中且靠右center left垂直居中且靠左lower center垂直居中且靠底部upper center垂直居中且靠頂部center居中...
plt.plot(x, y1, color="blue", linewidth=1.0, linestyle="-", label="y1")
plt.plot(x, y2, color="#800080", linewidth=2.0, linestyle="--", label="y2")
plt.legend(loc="upper left")
...
有時某些數據點非常關鍵,需要突顯出來。我們需要將改點繪製出來,即繪製散點圖,再對其做注釋。實現上述需求,我們要用到 scatter() 和 annotate() 函數。scatter() 是用於繪製散圖,這裡我們只是用其來繪製單個點。scatter() 用法,後續文章會詳細對其用法做說明。annotate() 則是添加標註 。
scatter() 函數必須傳入兩個參數 x 和 y。值得注意得是,它們的數據類型是列表。x 代表要標註點的橫軸位置,y 代表要標註點的橫軸位置。x 和 y 列表中下標相同的數據是對應的。例如 x 為 [3, 4],y 為 [6, 8],這表示會繪製點(3,6),(4, 8)。因此,x 和 y 長度要一樣。
annotate() 函數同樣也有兩個必傳參數,一個是標註內容,另一個是 xy。標註內容是一個字符串。xy 表示要在哪個位置(點)顯示標註內容。xy 位置地選定。一般是在 scatter() 繪製點附近,但不建議重合,這樣會影響美觀。
...
plt.plot(x, y1, color="blue", linewidth=1.0, linestyle="-", label="y1")
plt.scatter([3], [6], s=30, color="blue")
plt.annotate("(3, 6)",
xy=(3.3, 5.5),
fontsize=16,
xycoords='data')
plt.plot(x, y2, color="#800080", linewidth=2.0, linestyle="--", label="y2")
plt.scatter([3], [0], s=50, color="#800080")
plt.annotate("(3, 0)",
xy=(3.3, 0),
fontsize=16,
xycoords='data')
點已經被標註出來了,如果你還想給點添加注釋。這需要使用 text() 函數。text(x,y,s) 作用是在點(x,y) 上添加文本 s。matplotlib 目前好像對中午支持不是很友好,中文均顯示為亂碼。
...
plt.scatter([3], [0], s=50, color="#800080")
plt.annotate("(3, 0)", xy=(3.3, 0))
plt.text(4, -0.5, "this point very important",
fontdict={'size': 12, 'color': 'green'})
到此為止,我們基本上完成了繪製直線所有工作。Matplotlib 能繪製種類繁多且繪圖功能強大,所以我接下來的文章將單獨對每種類型圖做分享講解。
作者:猴哥
公眾號:極客猴
愛好讀書,喜歡鑽研技術,夢想成為文藝青年的 boy。