- 利用Python解決數學問題(原書第2版)
- (英)薩姆·莫利
- 3620字
- 2025-08-07 15:28:36
2.2 使用Matplotlib進行基本繪圖
圖形是理解行為的重要組成部分。通過簡單地繪制函數或數據,我們可以學到很多原本可能隱藏的信息。在本節中,我們將介紹如何使用Matplotlib繪制簡單函數或數據,設置圖形樣式,并為圖形添加標簽。
Matplotlib是一個非常強大的繪圖庫,這意味著使用它執行簡單任務可能會讓人望而生畏。對于那些習慣于使用MATLAB和其他數學軟件包的用戶來說,Matplotlib提供了一種基于狀態的接口,稱為pyplot。此外,還有一種面向對象的接口(OOI),它可能更適合更復雜的繪圖。在任一情況下,pyplot接口都是創建基本對象的便捷方式。
2.2.1 準備工作
通常,你想要繪制的數據將存儲在兩個獨立的NumPy數組中,為了清晰起見,我們將它們分別標記為x和y(在實踐中數據的命名方式并不重要)。我們將演示函數圖形的繪制過程,因此我們將生成一個數組x,并使用該函數生成相應的y值。我們將在相同的坐標軸上繪制3個不同的函數,范圍為-0.5≤x≤3:

讓我們使用Matplotlib在Python中繪制這3個函數。
2.2.2 實現方法
在繪制函數之前,我們必須生成要繪制的x和y數據。如果要繪制已經存在的數據,可以跳過這些命令。我們需要創建一組覆蓋所需范圍的x值,然后使用函數創建相應的y值:
1.NumPy中的linspace例程非常適合創建用于繪圖的數字數組。默認情況下,它會在指定的參數之間創建50個等間距的點。點的數量可以通過提供額外的參數來定制,但在大多數情況下,50個點已經足夠了:

2.一旦我們創建了x值,就可以生成相應的y值:

3.要繪制數據,首先需要創建一個新的圖形并附加坐標軸對象,可以通過不提供任何參數地調用plt.subplots例程來實現:

4.現在,我們在ax對象上使用plot方法繪制第一個函數。前兩個參數是要繪制的x和y坐標,第三個(可選)參數指定線的顏色為黑色:

5.為了幫助區分其他函數的圖形,我們使用虛線和點畫線繪制這些函數:

6.每個圖形都應該有標題和坐標軸標簽。在本例中,沒有什么有趣的內容可以用來標記坐標軸,因此我們只是用x和y來標記它們:

7.還可以添加圖例,以幫助你在不必查看其他地方的情況下區分不同函數的圖形:

8.最后,讓我們對圖形進行注釋,如使用文本標記函數g和h之間的交點:

這將在一個新圖形上繪制y值相對x值的關系圖。如果你正在使用IPython控制臺或Jupyter notebook,圖形應該會自動顯示;否則,你可能需要調用plt.show函數來使圖形顯示出來:

如果使用plt.show,該圖形應該會出現在新窗口中。在本章的后續示例中,我們不會再添加這個命令,但你應該知道,如果你不是在自動渲染圖形的環境(比如IPython控制臺或Jupyter notebook)中工作,你就需要使用它。生成的圖形應類似于圖2.1中的圖形。

圖2.1 同一個坐標系上的3個函數,每個函數都有不同的樣式,圖中帶有標簽、圖例和注釋
注意
如果你是在Jupyter notebook中使用的subplots命令,必須將對subplots例程的調用和其他繪圖命令放在同一個單元格中,否則圖形將無法生成。
2.2.3 原理解析
這里,我們使用了面向對象的接口(OOI),因為它允許我們精確地跟蹤繪圖的圖形(figure)對象和軸域(axes)對象。在只有一個圖形和軸域的情況下,這并不重要,但我們可以很容易地想象到可能同時有兩個或更多圖形和軸域的情況。遵循這種模式的另一個原因是在添加多個子圖時保持一致,詳見2.3節。
你可以使用以下命令序列,在基于狀態的接口中生成與上述示例相同的圖形:

如果當前沒有Figure或Axes對象,plt.plot例程將創建一個新的Figure對象,向該圖形添加一個新的Axes對象,并使用繪制的數據填充這個Axes對象。返回一個包含所畫線條的句柄列表,其中每個句柄都是Lines2D對象。在這種情況下,此列表將包含一個單獨的Lines2D對象。我們可以稍后使用這個Lines2D對象來進一步自定義線條的外觀。
請注意,在前面的代碼中,我們將所有對plot函數的調用組合在了一起。如果你使用的是OOI,這樣組合也是可行的。基于狀態的接口將參數傳遞給Axes方法,用于給檢索或創建的Axes對象設置屬性。
Matplotlib的對象層與一個底層的后端進行交互,后者負責生成圖形。plt.show函數向后端發出指令以渲染并呈現當前圖形。有許多后端可與Matplotlib一起使用,可以通過設置MPLBACKEND環境變量、修改matplotlibrc文件或在Python中調用matplotlib.use并提供備用后端的名稱來自定義。默認情況下,Matplotlib會基于可用的后端,選擇適合平臺(Windows、macOS、Linux)和符合目的(交互或非交互)的后端。例如,在作者的系統上,默認使用QtAgg后端,這是一個基于Anti-Grain Geometry(AGG)庫的交互式后端。或者,也可以使用QtCairo后端,該后端使用Cairo庫進行渲染。
注意
plt.show函數的作用不僅僅是在圖形上調用show方法,它還會連接到一個事件循環中以正確顯示圖形。因此應該使用plt.show例程來顯示圖形,而不是在Figure對象上使用show方法。
用于快速指定線條樣式的格式字符串由三個可選部分組成,每個部分都包含一個或多個字符。第一部分控制標記樣式(即在每個數據點處輸出的符號);第二部分控制連接數據點的線條樣式;第三部分控制圖形的顏色。在這個例子中,我們只指定了線條樣式。然而,可以同時指定線條樣式和標記樣式,或者只指定標記樣式。如果只提供標記樣式,則在數據點之間不繪制連接線。這對繪制不需要在數據點之間進行插值的離散數據非常有用。
有四種線條樣式參數可用:實線(-)、虛線(--)、點畫線(-.)和點線(:)。在格式字符串中只能指定有限數量的顏色,它們是紅色、綠色、藍色、青色、黃色、洋紅色、黑色和白色。格式字符串中表示顏色的字符是每種顏色對應英文單詞的第一個字母(黑色除外),因此這些顏色對應的字符分別是r、g、b、c、y、m、k和w。
在上述例子中,我們看到了這些格式字符串的三個示例:單一的k格式字符串只改變了線條的顏色,并保持其他設置為默認值(小的點標記和不間斷的線);k--和k.-格式字符串同時改變了顏色和線條樣式。有關更改點樣式的示例,請參見2.2.4節和圖2.2。

圖2.2 三組數據的散點圖,每組數據使用不同的標記樣式進行繪制
set_title、set_xlabel和set_ylabel方法簡單地將文本參數添加到Axes對象的相應位置。前面代碼中調用的legend方法,按照圖形順序給數據集添加相應的標簽,在本例中依次為y1、y2和y3。
可以向set_title、set_xlabel和set_ylabel例程提供許多關鍵字參數,以控制文本的樣式。例如,fontsize關鍵字可用于指定標簽字體的大小,通常以pt(磅)為單位。
Axes對象上的annotate方法可以將任意文本添加到圖的特定位置。此例程接受兩個參數:要顯示的字符串形式的文本和應該放置注釋的點的坐標。此例程還接受其他關鍵字參數,可用于自定義注釋的樣式。
2.2.4 更多內容
plt.plot例程接受可變數量的位置輸入。在前面的代碼中,我們提供了兩個位置參數,它們被解釋為x值和y值(按照順序)。如果我們只提供了一個數組,那么plot例程將會根據數據在數組中的位置進行繪制。也就是說,x的值取為0、1、2,以此類推。
plot方法還接受許多關鍵字參數,這些參數也可以用于控制圖形的樣式。如果同時存在關鍵字參數和格式字符串參數,關鍵字參數優先,并且它們適用于調用此繪制命令的所有數據集。控制標記樣式的關鍵字是marker,控制線條樣式的關鍵字為linestyle,控制顏色的關鍵字為color。color關鍵字參數接受許多不同的格式來指定顏色,包括(r, g, b)元組確定的RGB值(其中每個字符都是0到1之間的浮點數或十六進制字符串)。可以使用linewidth關鍵字參數來控制繪制的線條寬度,該參數應提供一個float數值。還有許多其他關鍵字參數可以傳遞給plot,Matplotlib文檔中給出了這樣的參數列表。許多關鍵字參數都有簡寫的版本,例如c表示color,lw表示linewidth。
在這個示例中,我們繪制了大量的坐標點,這些坐標點是根據選定的x值用求值函數生成的。在其他應用中,人們可能有來自真實世界的采樣數據(而不是生成的數據)。在這種情況下,最好去掉連接線,只在點上繪制標記。以下是如何實現這一點的示例:

這些命令的結果顯示在圖2.2中。Matplotlib有一種專門用于生成散點圖的方法,稱為scatter。
可以使用Axes對象上的方法來自定義圖形的其他方面。可以使用Axes對象上的set_xticks和set_yticks方法修改坐標軸刻度,使用grid方法配置網格的外觀。在pyplot接口中還有一些便捷的方法,它們可以將這些修改應用于當前的Axes對象(如果存在)。
例如,我們通過使用以下命令修改坐標軸的范圍,分別在x和y坐標軸上每隔0.5的倍數設置一個坐標軸刻度,并在圖中添加網格:

請注意,我們將坐標軸的范圍設置得稍微大于繪圖范圍,這是為了避免在繪圖窗口的邊界上放置標記。
除了這里描述的plot例程之外,Matplotlib還有許多其他繪圖例程。例如,有些繪圖方法使用不同的坐標軸比例,包括在x軸和y軸單獨使用對數坐標軸(semilogx或semilogy)或同時使用對數坐標軸(loglog)。這些在Matplotlib文檔中有詳細說明。如果想在Axes對象上繪制離散數據而不連接點,則scatter繪圖例程可能很有用,它還允許對標記的樣式進行更多的控制。例如,可以根據一些額外信息來調整標記的大小。
我們可以使用fontfamily關鍵字設置不同的字體,其值可以是字體的名稱,或者是serif、sans-serif、monospace,它們將選擇適當的內置字體。Matplotlib文檔中的matplotlib.text.Text類包含了完整的修飾符列表。
在例程中提供usetex=True參數,即可以使用TeX來呈現文本參數以進行額外的格式化。我們將在2.3節的例子中演示標簽的TeX格式化方法,如圖2.3所示。如果標題或軸標簽包含數學公式,這一功能特別有用。不幸的是,如果系統上沒有安裝TeX,則無法使用usetex關鍵字參數——在這種情況下,它會導致錯誤。然而,仍然可以使用TeX語法來格式化標簽中的數學文本,但這將由Matplotlib進行排版,而不是由Te X進行排版。