微實踐:繪制二元函數曲面
我們將演示如何借助于ufunc的廣播運算計算下述二元函數的在一個xy平面上的值并將其繪制成3D曲面。其中,x和y的取值范圍均為[-2,+2]。
為了達到目的,我們需要一個二維的結果數組z,其元素的下標對應參數x,y的取值,其元素的值則為上述函數的函數值。這可以通過廣播計算來得到。
本文節選自作者的《Python編程基礎及應用》視頻教程。Python編程基礎及應用_嗶哩嗶哩 (゜-゜)つロ 干杯~-bilibili?www.bilibili.com
np.ogrid是個特殊對象,通過切片下標來生成用于廣播運算的數組。先看下述程序:
#ogrid.py
x,y = np.ogrid[0:3:4j,0:4:5j]
print("x=\n",x)
print("y=\n",y)
print("x.shape=",x.shape)
print("y.shape=",y.shape)
執行結果:
x=
[[0.]
[1.]
[2.]
[3.]]
y=
[[0. 1. 2. 3. 4.]]
x.shape= (4, 1)
y.shape= (1, 5)
0:3:4j這種切片語法類似于np.linspace(0,3,4),它表示生成從0到3的包含4個元素的等差數列。這里的j并不表示復數的虛部,它只是一種語法格式。由于廣播的需要,x的形狀被設置為(4,1)。同理,由于廣播需要,y的形狀被設置成了(1,5)。這樣,通過ogrid生成的x和y數組符合廣播運算的規則,可以進行廣播運算。
下述代碼將x = [-2,+2],y = [-2, +2]的函數值矩陣以平面圖形式繪制。
#func2d.py
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import cm
y,x = np.ogrid[-2:2:200j,-2:2:200j]
z = x * np.exp(-x**2-y**2)
extent = [np.min(x),np.max(x),np.min(y),np.max(y)]
plt.imshow(z,extent=extent,cmap=cm.gray)
plt.colorbar()
plt.show()
根據ogrid的輸出,y,x分別是形狀為(200,1)和(1,200)的數組。z = x * np.exp(-x**2-y**2)的執行過程中將發生廣播,結果數組z將會是一個形狀為(200,200)的二維數組,元素值為對應x,y的函數值。如果將z視為一個圖像,那么其橫向x取值范圍對應[-2,+2],縱向y取值范圍取應[-2,+2]。
extent = [np.min(x),np.max(x),np.min(y),np.max(y)]將x及y的取值范圍放入一個列表。plt.imshow()函數將二維數組z作為圖像顯示,extent參數指明了橫縱坐標的范圍,cmap則指定了顏色映射對象,該顏色映射對象負責把z中的元素值轉換成像素點的顏色。plt.colorbar()則“聰明”通過顏色條顯示z中的函數值與顏色之間的對應關系。plt.show()真正地把圖表顯示出來。執行結果如下:
下述代碼將x = [-2,+2],y = [-2, +2]的函數值矩陣以3D圖形式繪制。
#func3d.py
import numpy as np
import mpl_toolkits.mplot3d
from matplotlib import pyplot as plt
from matplotlib import cm
x,y = np.mgrid[-2:2:20j,-2:2:20j]
z = x * np.exp(- x**2 - y**2)
fig = plt.figure(figsize=(8,6))
ax = fig.gca(projection='3d')
ax.plot_surface(x,y,z,cmap=cm.ocean)
plt.show()
ax是表示一個子圖,由于ax.plot_surface()函數要求x,y,z三個數組都必須是相同形狀的二維數組,所以上述代碼中沒有使用ogrid來生成廣播數組,而是使用了mgrid。mgrid的功能與ogrid相近,區別在于其返回的是已經進行了形狀擴充的數組。也就是說,上述通過mgrid生成出來的x,y數組的形狀已經是(20,20)。讀者可以自行打印x,y的值出來觀察mgrid對象的用法。讀者如果對matplotlib相關代碼感到疑惑,請先略過,本書后續部分將解讀matplotlib包的使用。上述程序執行結果如下:
本文節選自作者的B站MOOC及同名教材:Python編程基礎及應用 — 重慶大學 高等教育出版社,作者親授_嗶哩嗶哩 (゜-゜)つロ 干杯~-bilibili?www.bilibili.com版權聲明 本文可以在互聯網上自由轉載,但必須:注明出處(作者:海洋餅干叔叔)并包含指向本頁面的鏈接。 本文不可以以紙質出版為目的進行改編、摘抄。