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