在〈陣列程式設計〉中看到的範例,都是自行指定 list
來建立 NumPy 的陣列,實際上只要是類陣列(array like),也就是實作了 __array__
方法的物件,都可以作為 numpy.array
的第一個引數。
在 NumPy 中要建立陣列也有其他的方式,然而,不需要一次性地全部認識,而是在日後各自需求發生,在搜尋引掌或 API 文件搜尋看看有沒有合用對象就可以了。
為了讓需求有趣一點,在這邊先簡略談談 Matplotlib,看看我玩圖學、OpenSCAD、WebGL、p5.js 應該可以發覺,我是一個很圖像化思考的人,如果讓執行結果可以圖像化表示,一來可以有個具體實現目標,二來在學習成果的回饋上也會有趣一些。
Matplotlib 的功能也是很多,如同 NumPy,不需要一次性地全部認識 Matplotlib,遇到需求再逐一認識探索就可以了。
那麼這邊的第一個需求就是畫出函式 y = a * x + b
的圖形,在這需求下,首先是用最簡單的方式秀出 Matplotlib 視窗:
import matplotlib.pyplot as plt
plt.title('y = a * x + b') # 顯示標題
plt.xlabel('x') # x 軸標示
plt.ylabel('y') # y 軸標示
plt.show()
matplotlib.pyplot
是繪圖時必要的模組,使用 title
設定標題後呼叫 show
,就可以顯示 Matplotlib 視窗,這邊也透過 xlabel
、ylabel
設定了標示文字,執行後就會看到以下畫面:
可以使用 plot
方法指定 x、y 座標來畫出函式圖形,plot
的第一個參數接受全部的 x 值,第二個參數接受全部的 y 值,Matplotlib 常見與 NumPy 結合使用,然而這不是必要的,其實各可以使用 list
指定,只不過在程式碼的表達上會有差異。例如:
import matplotlib.pyplot as plt
a = 0.25
b = 15
xs = [x for x in range(-10, 11)]
ys = [a * x + b for x in xs]
plt.title('y = a * x + b')
plt.xlabel('x')
plt.ylabel('y')
plt.plot(xs, ys)
plt.show()
這會畫出以下的圖形:
pyplot
預設會自行決定寬高比例,因此可以看到,x 與 y 軸的間距單位並不相同,自行拉動視窗改變大小,圖形的寬高比例也會自行調整。
如果想指定寬高比例,可以使用 gca
方法取得目前軸(get current axes)的代表物件,然後呼叫它的 set_aspect
設定寬高比,例如,設為 1:
import matplotlib.pyplot as plt
a = 0.25
b = 15
xs = [x for x in range(-10, 11)]
ys = [a * x + b for x in xs]
plt.title('y = a * x + b')
plt.xlabel('x')
plt.ylabel('y')
plt.gca().set_aspect(1) # 設定寬高比
plt.plot(xs, ys)
plt.show()
這麼一來,寬高比例就是固定的,拉動視窗改變大小,圖形的寬高比例也不會改變:
雖然上頭使用了 for comprehension,不過依然是程式設計者的角度在實現需求,該是轉換思維,使用 NumPy 的時候了:
import numpy as np
import matplotlib.pyplot as plt
a = 0.25
b = 15
x = np.arange(-10, 11) # 建立 NumPy 陣列
y = a * x + b # 直接進行 a * x + b
plt.title('y = a * x + b')
plt.xlabel('x')
plt.ylabel('y')
plt.gca().set_aspect(1)
plt.plot(x, y) # 指定兩個軸的陣列
plt.show()
arange
可以用來指定範圍建立陣列,就跟 Python 內建的 range
一樣,arange
建立的範圍不包含第二個引數指定的數字,接著就直接進行 a * x + b
,NumPy 的陣列與 list
的特性相近,直接指定給 plot
就可以繪圖了,執行結果與上圖相同。
因此,日後要畫函式圖,就不要再以迴圈的概念來思考了,而是用建立一組資料,運算一組資料的方式來思考,例如,想畫個 sin
波嗎?NumPy 有個 sin
,可以接受徑度陣列:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 2 * np.pi, np.pi / 180) # 0 到 2 * PI,步進值 PI / 180
y = np.sin(x)
plt.title('y = sin(x)')
plt.xlabel('x')
plt.ylabel('y')
plt.gca().set_aspect(1)
plt.plot(x, y)
plt.show()
arange
的第三個參數是步進值,預設是 1,上頭指定為 PI / 180,畫出來的圖形是: