直方图是我们常常可以作为我们理解数据集的第一步,也是重要一步。

一维直方图绘制

首先还是基操:

  1. %matplotlib inline
  2. import matplotlib.pyplot as plt
  3. plt.style.use('seaborn-white')
  4. import numpy as np
  5. data = np.random.randn(1000)
  1. plt.hist(data)

image.png
当然 plt.hist() 函数还有很多可选参数:

  1. plt.hist(data, bins=30, density=True, alpha=0.5,
  2. histtype='stepfilled', color='steelblue',
  3. edgecolor='none')

image.png

  • bins —- 直方图中箱子 ( bins ) 的数量
  • density —- 如果该参数为 True ,则将直方图正则化,也即直方图下方的面积和为 1.


直接查看 plt.hist() 的官方文档还是更靠谱的,每个参数都解释的很明白。
histtype='stepfilled'** 与透明度 alpha 一起使用以在直方图中对比不同数据的分布效果更佳呦!**

  1. x1 = np.random.normal(0, 0.8, 1000)
  2. x2 = np.random.normal(-2, 1, 1000)
  3. x3 = np.random.normal(3, 2, 1000)
  4. kwargs = dict(histtype='stepfilled', alpha=0.3, density=True, bins=40)
  5. plt.hist(x1, **kwargs)
  6. plt.hist(x2, **kwargs)
  7. plt.hist(x3, **kwargs)

image.png

需要说明的是, plt.hist() 是有返回值的。如果我们只想计算直方图参数(计算每一个 bins 中点的数量)而不把直方图画出来,那么可以使用 np.histogram()

  1. >>> counts, bin_edges = np.histogram(data, bins=5)
  2. >>> print(counts, bin_edges)
  3. [ 18 200 432 302 48] [-3.35181513 -2.10033581 -0.84885649 0.40262284 1.65410216 2.90558149]

二维直方图绘制

上面我们在绘制一维直方图的时候,通过将一条数轴(x 轴)划分成多个 bins 的方法画出了直方图。那么二维直方图同理,要将一个个二维点分入不同的 bins 里面。比如下面我们定义了一些服从多变量高斯分布的数据点:

  1. mean = [0, 0]
  2. cov = [[1, 1], [1, 2]]
  3. x, y = np.random.multivariate_normal(mean, cov, 10000).T

plt.hist2d() : 二维直方图

  1. plt.hist2d(x, y, bins=30, cmap='Blues')
  2. cb = plt.colorbar()
  3. cb.set_label('counts in bins')

image.png

plt.hist() 一样, plt.hist2d() 也有在 Numpy 中对应的函数 np.histogram2d() :

  1. counts, xedges, yedges = np.histogram2d(x, y, bins=30)


如果想得到高于二维的直方图参数,可以使用 np.histogramdd() 函数

plt.hexbin() : 六边形 bins

上面画出来的直方图使用正方形进行密铺,另外一种常用的密铺形状是正六边形。Matplotlib 也提供了相应的接口:

  1. plt.hexbin(x, y, gridsize=30, cmap='Blues')
  2. cb = plt.colorbar(label='count in bin')

image.png
plt.hexbin() 提供了一堆有意思的可选参数,比如可以指明每一个点的权重,改变返回值的形式等,详见该函数的 docstring.

核密度估计 Kernel density estimation

另外一个估计高维数据的密度的方法是核密度估计 (KDE, Kernel Density Estimation). 可以使用 scipy.stats 包直接整!

  1. from scipy.stats import gaussian_kde
  2. # fit an array of size [Ndim, Nsamplpes]
  3. data = np.vstack([x, y])
  4. kde = gaussian_kde(data)
  5. # evaluate on a regular grid
  6. xgrid = np.linspace(-3.5, 3.5, 40)
  7. ygrid = np.linspace(-6, 6, 40)
  8. Xgrid, Ygrid = np.meshgrid(xgrid, ygrid)
  9. Z = kde.evaluate(np.vstack([Xgrid.ravel(), Ygrid.ravel()]))
  10. # Plot the result as an image
  11. plt.imshow(Z.reshape(Xgrid.shape),
  12. origin='lower', aspect='auto',
  13. extent=[-3.5, 3.5, -6, 6],
  14. cmap='Blues')
  15. cb = plt.colorbar()
  16. cb.set_label('density')

image.png