在這段代碼中又出現(xiàn)了一個(gè)新的東西叫做,一個(gè)用ax命名的對(duì)象。在Matplotlib中,畫(huà)圖時(shí)有兩個(gè)常用概念,一個(gè)是平時(shí)畫(huà)圖蹦出的一個(gè)窗口,這叫一個(gè)figure。Figure相當(dāng)于一個(gè)大的畫(huà)布,在每個(gè)figure中,又可以存在多個(gè)子圖,這種子圖叫做axes。顧名思義,有了橫縱軸就是一幅簡(jiǎn)單的圖表。在上面代碼中,先把figure定義成了一個(gè)一行兩列的大畫(huà)布,然后通過(guò)fig.add_subplot()加入兩個(gè)新的子圖。subplot的定義格式很有趣,數(shù)字的前兩位分別定義行數(shù)和列數(shù),最后一位定義新加入子圖的所處順序,當(dāng)然想寫(xiě)明確些也沒(méi)問(wèn)題,用逗號(hào)分開(kāi)即可。。上面這段代碼產(chǎn)生的圖像如下:
5.3.1 3D圖表
Matplotlib中也能支持一些基礎(chǔ)的3D圖表,比如曲面圖,散點(diǎn)圖和柱狀圖。這些3D圖表需要使用mpl_toolkits模塊,先來(lái)看一個(gè)簡(jiǎn)單的曲面圖的例子:
import matplotlib.pyplot as plt
import numpy as np
# 3D圖標(biāo)必須的模塊,project='3d'的定義
from mpl_toolkits.mplot3d import Axes3D
np.random.seed(42)
n_grids = 51 # x-y平面的格點(diǎn)數(shù)
c = n_grids / 2 # 中心位置
nf = 2 # 低頻成分的個(gè)數(shù)
# 生成格點(diǎn)
x = np.linspace(0, 1, n_grids)
y = np.linspace(0, 1, n_grids)
# x和y是長(zhǎng)度為n_grids的array
# meshgrid會(huì)把x和y組合成n_grids*n_grids的array,X和Y對(duì)應(yīng)位置就是所有格點(diǎn)的坐標(biāo)
X, Y = np.meshgrid(x, y)
# 生成一個(gè)0值的傅里葉譜
spectrum = np.zeros((n_grids, n_grids), dtype=np.complex)
# 生成一段噪音,長(zhǎng)度是(2*nf+1)**2/2
noise = [np.complex(x, y) for x, y in np.random.uniform(-1,1,((2*nf+1)**2/2, 2))]
# 傅里葉頻譜的每一項(xiàng)和其共軛關(guān)于中心對(duì)稱
noisy_block = np.concatenate((noise, [0j], np.conjugate(noise[::-1])))
# 將生成的頻譜作為低頻成分
spectrum[c-nf:c+nf+1, c-nf:c+nf+1] = noisy_block.reshape((2*nf+1, 2*nf+1))
# 進(jìn)行反傅里葉變換
Z = np.real(np.fft.ifft2(np.fft.ifftshift(spectrum)))
# 創(chuàng)建圖表
fig = plt.figure('3D surface & wire')
# 第一個(gè)子圖,surface圖
ax = fig.add_subplot(1, 2, 1, projection='3d')
# alpha定義透明度,cmap是color map
# rstride和cstride是兩個(gè)方向上的采樣,越小越精細(xì),lw是線寬
ax.plot_surface(X, Y, Z, alpha=0.7, cmap='jet', rstride=1, cstride=1, lw=0)
# 第二個(gè)子圖,網(wǎng)線圖
ax = fig.add_subplot(1, 2, 2, projection='3d')
ax.plot_wireframe(X, Y, Z, rstride=3, cstride=3, lw=0.5)
plt.show()
這個(gè)例子中先生成一個(gè)所有值均為0的復(fù)數(shù)array作為初始頻譜,然后把頻譜中央部分用隨機(jī)生成,但同時(shí)共軛關(guān)于中心對(duì)稱的子矩陣進(jìn)行填充。這相當(dāng)于只有低頻成分的一個(gè)隨機(jī)頻譜。最后進(jìn)行反傅里葉變換就得到一個(gè)隨機(jī)波動(dòng)的曲面,圖像如下:
3D的散點(diǎn)圖也是常常用來(lái)查看空間樣本分布的一種手段,并且畫(huà)起來(lái)比表面圖和網(wǎng)線圖更加簡(jiǎn)單,來(lái)看例子:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
np.random.seed(42)
# 采樣個(gè)數(shù)500
n_samples = 500
dim = 3
# 先生成一組3維正態(tài)分布數(shù)據(jù),數(shù)據(jù)方向完全隨機(jī)
samples = np.random.multivariate_normal(
np.zeros(dim),
np.eye(dim),
n_samples
)
# 通過(guò)把每個(gè)樣本到原點(diǎn)距離和均勻分布吻合得到球體內(nèi)均勻分布的樣本
for i in range(samples.shape[0]):
r = np.power(np.random.random(), 1.0/3.0)
samples[i] *= r / np.linalg.norm(samples[i])
upper_samples = []
lower_samples = []
for x, y, z in samples:
# 3x+2y-z=1作為判別平面
if z > 3*x + 2*y - 1:
upper_samples.append((x, y, z))
else:
lower_samples.append((x, y, z))
fig = plt.figure('3D scatter plot')
ax = fig.add_subplot(111, projection='3d')
uppers = np.array(upper_samples)
lowers = np.array(lower_samples)
# 用不同顏色不同形狀的圖標(biāo)表示平面上下的樣本
# 判別平面上半部分為紅色圓點(diǎn),下半部分為綠色三角
ax.scatter(uppers[:, 0], uppers[:, 1], uppers[:, 2], c='r', marker='o')
ax.scatter(lowers[:, 0], lowers[:, 1], lowers[:, 2], c='g', marker='^')
plt.show()
這個(gè)例子中,為了方便,直接先采樣了一堆3維的正態(tài)分布樣本,保證方向上的均勻性。然后歸一化,讓每個(gè)樣本到原點(diǎn)的距離為1,相當(dāng)于得到了一個(gè)均勻分布在球面上的樣本。再接著把每個(gè)樣本都乘上一個(gè)均勻分布隨機(jī)數(shù)的開(kāi)3次方,這樣就得到了在球體內(nèi)均勻分布的樣本,最后根據(jù)判別平面3x+2y-z-1=0對(duì)平面兩側(cè)樣本用不同的形狀和顏色畫(huà)出,圖像如下:
5.3.1 圖像顯示
評(píng)論