# Matplotlib 繪圖技巧:在同一張圖上繪製兩個函數、兩張圖並列 > 作者:王一哲 日期:2018/11/20 我們在〈[冰與水蒸氣混合達熱平衡時溫度與質量比值關係圖](https://hackmd.io/s/B1oZPnpaX)〉中使用 Matplotlib 繪製單一的函數圖形,但如果我們想在同一張圖上繪製兩個函數,或是將兩張圖並列畫在同一張圖片中時要怎麼做呢? 我們以兩個點電荷之間的靜電力和電位能與距離的關係為例,假設點電荷的電量分別為 Q 和 q,兩者之間的距離為 r,則兩者之間的靜電力量值 $$F = \frac{kQq}{r^2}$$ 電位能量值 $$U = \frac{kQq}{r}$$ 由於使用 Matplotlib 繪圖時必須代入數值,我將數值設定為 $Q = 1 \times 10^{-4} ~\mathrm{C}$、$q = 1 \times 10^{-4} ~\mathrm{C}$、$0.01 \leq r \leq 10~\mathrm{m}$,r 不從 0 開始畫是為了避免靜電力和電位能量值變為無窮大。接著我們來繪製函數圖形。 <br></br> ## 在同一張圖上繪製兩個函數 我們希望圖片能有以下的特點: 1. 用不同的顏色繪製不同的函數 2. 加上圖例、格線、坐標軸標籤 3. 設定縱軸繪圖範圍 成果如下圖所示,使用的程式碼如下。 <img height="80%" width="80%" src="https://i.imgur.com/govT5Y1.png" style="display: block; margin-left: auto; margin-right: auto;"/> <div style="text-align:center">在同一張圖上繪製靜電力、電位能與距離的關係圖</div> <br></br> ```python= """ 靜電力、電位能對距離的關係圖 日期: 2018/11/5 作者: 王一哲 """ import numpy as np # 引入科學計算函式庫 import matplotlib.pyplot as plt # 引入繪圖函式庫 xmin, xmax, num = 0.01, 10, 100 # 設定繪圖範圍、取點數 x = np.linspace(xmin, xmax, num) # 產生x Q = 1E-4 q = 1E-4 k = 8.988E9 F = k * Q * q / x**2 # 靜電力F U = k * Q * q / x # 電位能U plt.figure(figsize = (6, 4.5), dpi = 100) # 設定圖片尺寸 plt.xlabel('r (m)', fontsize = 16) # 設定坐標軸標籤 plt.xticks(fontsize = 12) # 設定坐標軸數字格式 plt.yticks(fontsize = 12) plt.grid(color = 'red', linestyle = '--', linewidth = 1) # 設定格線顏色、種類、寬度 plt.ylim(0, 200) # 設定y軸繪圖範圍 # 繪圖並設定線條顏色、寬度、圖例 line1, = plt.plot(x, F, color = 'red', linewidth = 3, label = 'Electric Force (N)') line2, = plt.plot(x, U, color = 'blue', linewidth = 3, label = 'Electric Potential Energy (J)') plt.legend(handles = [line1, line2], loc='upper right') plt.savefig('Fe_r_plot.svg') # 儲存圖片 plt.savefig('Fe_r_plot.png') plt.show() # 顯示圖片 ``` <br></br> 以下說明程式碼中較特別的部分 1. 使用 **plt.xlabel('r (m)', fontsize = 16)** 設定 x 軸標籤為 r (m),字型大小為 16。 2. 使用 **plt.grid(color = 'red', linestyle = '--', linewidth = 1)** 加上格線,格線為紅色虛線,線條寬度為 1。 3. 使用 **plt.ylim(0, 200)** 設定y軸繪圖範圍為 1 到 200。 4. 為了用不同的線條顏色繪製不同的函數,我們使用了以下的程式碼,括號中的選項有:**顏色** (**color**)、**線條寬度** (**linewidth**)、**標籤** (**label**)。由於 plt.plot 的回傳值不是一個單純的物件,如果我們要將繪製的線條物件指定給 line1 和 line2,**line1 和 line2 後方一定要加上逗號**。 ```python line1, = plt.plot(x, F, color = 'red', linewidth = 3, label = 'Electric Force (N)') line2, = plt.plot(x, U, color = 'blue', linewidth = 3, label = 'Electric Potential Energy (J)') ``` 5. 使用 **plt.legend(handles = [line1, line2], loc='upper right')** 加上圖例,其中 **handles** 是圖例的內容,在此設定為 line1 和 line2 的標籤;**loc**是圖例的位置,在此設定為右上方。如果想要知道更詳細的設定,請參考官方說明書 https://matplotlib.org/api/_as_gen/matplotlib.pyplot.legend.html <br></br> ## 將兩張圖並列畫在同一張圖片中 我們希望圖片能有以下的特點: 1. 左、右兩張圖並列 2. 兩張圖共同相同格式的縱軸 3. 加坐標軸標籤 4. 設定縱軸繪圖範圍 成果如下圖所示,使用的程式碼如下。 <img height="100%" width="100%" src="https://i.imgur.com/uvscOWC.png" style="display: block; margin-left: auto; margin-right: auto;"/> <div style="text-align:center">將靜電力、電位能與距離的關係圖並列於同一張圖中</div> <br></br> ```python= """ 靜電力、電位能對距離的關係圖, 兩圖並列 日期: 2018/11/18 作者: 王一哲 """ import numpy as np # 引入科學計算函式庫 import matplotlib.pyplot as plt # 引入繪圖函式庫 xmin, xmax, num = 0.01, 10, 100 # 設定繪圖範圍、取點數 x = np.linspace(xmin, xmax, num) # 產生x Q, q, k = 1E-4, 1E-4, 8.988E9 # 點電荷電量及靜電力常數 F = k * Q * q / x**2 # 靜電力F U = k * Q * q / x # 電位能U # 建立繪圖物件 fig, 大小為 12 * 4.5, 內有 1 列 2 欄的小圖, 兩圖共用 x 軸和 y 軸 fig, (ax1, ax2) = plt.subplots(1, 2, sharex = True, sharey = True, figsize = (12, 4.5)) # 設定小圖 ax1 的坐標軸標籤, 格線顏色、種類、寬度, y軸繪圖範圍, 最後用 plot 繪圖 ax1.set_xlabel('r (m)', fontsize = 16) ax1.set_ylabel('F (N)', fontsize = 16) ax1.grid(color = 'red', linestyle = '--', linewidth = 1) ax1.set_ylim(0, 200) ax1.plot(x, F, color = 'blue', linewidth = 3) # 設定小圖 ax2 的坐標軸標籤, 格線顏色、種類、寬度, 最後用 plot 繪圖 ax2.set_xlabel('r (m)', fontsize = 16) ax2.set_ylabel('U (J)', fontsize = 16) ax2.grid(color = 'red', linestyle = '--', linewidth = 1) ax2.plot(x, U, color = 'blue', linewidth = 3) # 用 savefig 儲存圖片, 用 show 顯示圖片 fig.savefig('Fe_r_plot_2.svg') fig.savefig('Fe_r_plot_2.png') fig.show() ``` <br></br> 以下說明程式碼中較特別的部分 1. 使用 **fig, (ax1, ax2) = plt.subplots(1, 2, sharex = True, sharey = True, figsize = (12, 4.5))** 建立多張圖的繪圖物件,其中 a. **1, 2** 代表物件中有 1 列 2 欄的小圖 b. **sharex = True** 代表共用 x 軸坐標 c. **sharey = True** 代表共用 y 軸坐標 d. **figsize = (12, 4.5)** 將物件尺寸設定為 12 吋乘以 4.5 吋。 e. 整個繪圖物件指定給 fig f. 兩張小圖分別指定給 ax1 和 ax2 2. 使用 **ax1.set_xlabel** 設定ax1 的 x 坐標軸標籤,使用 **ax1.set_ylabel** 設定ax1 的 y 坐標軸標籤 ,使用 **ax1.set_ylim(0, 200)** 設定y軸繪圖範圍為 1 到 200。 3. ax2 的設定方法與 ax1 相似,但是我們已經設定兩共用 y 軸格式,不需要再設定 ax2.set_ylim(0, 200)。 <br></br> ## 結語 這是一些使用 Matplotlib 繪圖的筆記,如果想要看更多的繪圖實例,請參考 https://python-graph-gallery.com/ <br></br> --- ###### tags:`Physics`、`Python`