接着上篇,一個簡單的直方圖可以是我們開始理解數據集的第一步。前面我們看到了 Matplotlib 的直方圖函數,我們可以用一行代碼繪制基礎的直方圖,當然首先需要將需要用的包導入 Pycharm:
import numpy as np import matplotlib.pyplot as plt plt.style.use('seaborn-white') data = np.random.randn(1000)
plt.hist(data);
plt.show()
hist()
函數有很多的參數可以用來調整運算和展示;下面又一個更加個性化的直方圖展示:
譯者注:normed 參數已經過時,此處對代碼進行了相應修改,使用了替代的 density 參數。將上代碼plt.hist(data);改為如下:
plt.hist(data, bins=30, density=True, alpha=0.5, histtype='stepfilled', color='steelblue', edgecolor='none');
plt.hist
文檔中有更多關於個性化參數的信息。作者發現聯合使用histtype='stepfilled'
和alpha
參數設置透明度在對不同分布的數據集進行比較展示時很有用:
x1 = np.random.normal(0, 0.8, 1000) x2 = np.random.normal(-2, 1, 1000) x3 = np.random.normal(3, 2, 1000) kwargs = dict(histtype='stepfilled', alpha=0.3, density=True, bins=40) plt.hist(x1, **kwargs) plt.hist(x2, **kwargs) plt.hist(x3, **kwargs);
如果你只是需要計算直方圖的數值(即每個桶的數據點數量)而不是展示圖像,np.histogram()
函數可以完成這個目標:
counts, bin_edges = np.histogram(data, bins=5) print(counts)
[ 49 273 471 183 24]
二維直方圖和分桶
正如前面我們可以在一維上使用數值對應的直線划分桶一樣,我們也可以在二維上使用數據對應的點來划分桶。本節我們介紹幾種實現的方法。首先定義數據集,從多元高斯分布中獲得x
和y
數組:
mean = [0, 0] cov = [[1, 1], [1, 2]] x, y = np.random.multivariate_normal(mean, cov, 10000).T
plt.hist2d
:二維直方圖
繪制二維直方圖最直接的方法是使用 Matplotlib 的plt.hist2d
函數:
plt.hist2d(x, y, bins=30, cmap='Blues') cb = plt.colorbar() cb.set_label('counts in bin')
類似plt.hist
,plt.hist2d
有許多額外的參數來調整分桶計算和圖表展示,可以通過文檔了解更多信息。而且,plt.hist
有np.histogram
,plt.hist2d
也有其對應的函數np.histogram2d
。如下例:
counts, xedges, yedges = np.histogram2d(x, y, bins=30)
如果要獲得更高維度的分桶結果,參見np.histogramdd
函數文檔。
plt.hexbin
:六角形分桶
剛才的二維分桶是沿着坐標軸將每個桶分為正方形。另一個很自然的分桶形狀就是正六邊形。對於這個需求,Matplotlib 提供了plt.hexbin
函數,它也是在二維平面上分桶展示,不過每個桶(即圖表上的每個數據格)將會是六邊形:
plt.hexbin(x, y, gridsize=30, cmap='Blues') cb = plt.colorbar(label='count in bin')
plt.hexbin
有許多有趣的參數,包括能對每個點設置權重和將每個桶的輸出數據結果改為任意的 NumPy 聚合結果(帶權重的平均值,帶權重的標准差等)。
核密度估計
另外一個常用來統計多維數據密度的工具是核密度估計(KDE)。這目前我們只需要知道 KDE 被認為是一種可以用來填補數據的空隙並補充上平滑變化數據的方法就足夠了。快速和簡單的 KDE 算法已經在scipy.stats
模塊中有了成熟的實現。下面我們就一個簡單的例子來說明如何使用 KDE 和繪制相應的二維直方圖:
from scipy.stats import gaussian_kde
mean = [0, 0]
cov = [[1, 1], [1, 2]]
x, y = np.random.multivariate_normal(mean, cov, 10000).T
# 產生和處理數據,初始化KDE
data = np.vstack([x, y])
kde = gaussian_kde(data)
# 在通用的網格中計算得到Z的值
xgrid = np.linspace(-3.5, 3.5, 40)
ygrid = np.linspace(-6, 6, 40)
Xgrid, Ygrid = np.meshgrid(xgrid, ygrid)
Z = kde.evaluate(np.vstack([Xgrid.ravel(), Ygrid.ravel()]))
# 將圖表繪制成一張圖像
plt.imshow(Z.reshape(Xgrid.shape),
origin='lower', aspect='auto',
extent=[-3.5, 3.5, -6, 6],
cmap='Blues')
cb = plt.colorbar()
cb.set_label("density")
plt.show()
KDE 有着光滑的長度,可以在細節和光滑度中有效的進行調節(一個例子是方差偏差權衡)。這方面有大量的文獻介紹:高斯核密度估計gaussian_kde
使用了經驗法則來尋找輸入數據附近的優化光滑長度值。
其他的 KDE 實現也可以在 SciPy 中找到,每一種都有它的優點和缺點;
參見sklearn.neighbors.KernelDensity
和statsmodels.nonparametric.kernel_density.KDEMultivariate
。要繪制基於 KDE 進行可視化的圖表,Matplotlib 寫出的代碼會比較冗長。