2018年6月13日 星期三

使用 matplotlib 繪製函數及數據圖

使用 matplotlib 繪製函數及數據圖


日期:2018/6/13

繪製函數圖


我之前曾經用 Gnuplot 畫函數圖形,但自從學了 Python 以及 matplotlib 之後,就想要用 Python 來畫圖,下圖是 -4π ≤ x ≤ +4π 範圍內對應的 sin(x) 圖形,下方則是程式碼。



"""
 Python筆記: 2D曲線圖
 日期: 2018/6/13
 作者: 王一哲
"""
import numpy as np                                        # 引入科學計算函式庫
import matplotlib.pyplot as plt                           # 引入繪圖函式庫

xmin, xmax, num = -4*np.pi, 4*np.pi, 1000                 # 設定繪圖範圍、取點數
x = np.linspace(xmin, xmax, num)                          # 產生x
y = np.sin(x)                                             # 產生y

plt.figure(figsize = (8, 6), dpi = 100)                   # 設定圖片尺寸
plt.xlabel('x(rad)', fontsize = 16)                       # 設定坐標軸標籤
plt.ylabel('sin(x)', fontsize = 16)
plt.xticks(fontsize = 12)                                 # 設定坐標軸數字格式
plt.yticks(fontsize = 12)
plt.grid(color = 'red', linestyle = '--', linewidth = 1)  # 設定格線顏色、種類、寬度
plt.plot(x, y, color = 'blue', linewidth = 3)             # 繪圖並設定線條顏色、寬度
plt.savefig('plot_2D.svg')                                # 儲存圖片
plt.savefig('plot_2D.png')
plt.show()                                                # 顯示圖片




繪製數據圖


我在之前的文章〈使用for迴圈計算水平抛射資料〉當中,利用 for 迴圈計算相同的水平初速、不同的抛出高度 h 對應的水平射程 R,再將資料存成文字檔。如果想要用 matplotlib
直接作圖,只需要加上一部分的程式碼即可,成果如下圖,下方則是程式碼。雖然這樣做很方便,但是我比較希望學生將資料丟進 SciDAVis 這類的軟體中,順便學習處理數據的方法。


"""
 VPython教學: 5-5.水平抛射, 用for迴圈改變h, 記錄t、R
 Ver. 1: 2018/3/21
 Ver. 2: 2018/6/13  加上用 matplotlib.pyplot 繪圖的部分
 作者: 王一哲
"""
from vpython import *
import matplotlib.pyplot as plt

"""
 1. 參數設定, 設定變數及初始值
"""
size = 1     # 小球半徑
v0 = 5       # 小球水平初速
L = 50       # 地板長度
g = 9.8      # 重力加速度 9.8 m/s^2
dt = 0.001   # 時間間隔
data_h, data_x = [], []     # 儲存繪圖資料的串列

"""
 2. 畫面設定
"""
scene = canvas(title = "Projectile", width = 800, height = 600, x = 0, y = 0, center = vector(0, 5, 0), \
                          background = vector(0, 0.6, 0.6))
floor = box(pos = vector(0, -size, 0), length = L, height = 0.01, width = 10, texture = textures.metal)

# 開啟檔案 data.txt, 屬性為寫入, 先寫入欄位的標題
file = open("data.txt", "w", encoding = "UTF-8")
file.write("h(m), t(s), R(m)\n")

"""
 3. 用for迴圈改變h, 計算t、R, 寫入檔案
"""
for h in range(5, 51, 1):
    t = 0
    ball = sphere(pos = vector(-L/2, h, 0), radius = size, texture = textures.wood, make_trail = True)
    ball.v = vector(v0, 0, 0)
    ball.a = vector(0, -g, 0)
# 物體運動部分
    while(ball.pos.y > floor.height/2):
#        rate(500)
        ball.v += ball.a*dt
        ball.pos += ball.v*dt
        t += dt
    print(h, t, ball.pos.x + L/2)
    file.write(str(h) + "," + str(t) + "," + str(ball.pos.x + L/2) + "\n")
    data_h.append(h)
    data_x.append(ball.pos.x + L/2)

file.close() # 關閉檔案

# 用 matplotlib.pyplot 繪圖
plt.figure(figsize = (8, 6), dpi = 100)                   # 設定圖片尺寸
plt.title('h - R plot', fontsize = 18)                    # 設定圖標題
plt.xlabel('h(m)', fontsize = 16)                         # 設定坐標軸標籤
plt.ylabel('R(m)', fontsize = 16)
plt.xticks(fontsize = 12)                                 # 設定坐標軸數字格式
plt.yticks(fontsize = 12)
plt.grid(color = 'red', linestyle = '--', linewidth = 1)  # 設定格線顏色、種類、寬度
plt.plot(data_h, data_x, marker = 'o', markerfacecolor = 'blue', markersize = 8, color = 'skyblue', linewidth = 3)   # 繪圖並設定線條顏色、寬度
plt.legend(loc='upper right', fontsize = 14)
plt.savefig('h-R_plot.svg')                               # 儲存圖片
plt.savefig('h-R_plot.png')
plt.show()                                                # 顯示圖片


參考資料

  1. https://python-graph-gallery.com/122-multiple-lines-chart/
  2. https://morvanzhou.github.io/tutorials/data-manipulation/plt/

2 則留言:

  1. 回覆
    1. 我是用 matplotlib.font_manager.FontProperties 搭配 Windows 內建的宋體字 simsun.ttc,可以參考以下的程式碼。


      from matplotlib.font_manager import FontProperties
      import matplotlib.pyplot as plt
      import numpy as np

      xmin = -4*np.pi
      xmax = 4*np.pi
      num = 200
      x = np.linspace(xmin, xmax, num)
      y = np.sin(x)

      font = FontProperties(size = '18')
      font_title = FontProperties(fname = r"C:\Windows\Fonts\simsun.ttc", size = '24')

      plt.figure(figsize=(8, 6), dpi=72)

      plt.xlim(xmin,xmax)
      plt.xlabel(r"x", fontproperties = font)
      plt.ylabel(r"sin(x)", fontproperties = font)
      plt.title("正弦函數", fontproperties = font_title)
      plt.grid(True)

      plt.plot(x, y)
      plt.savefig('fig.png')
      plt.show()

      刪除