嗯,kde 的面积是 1。要绘制与直方图匹配的 kde,需要将 kde 乘以直方图的面积。
对于密度图,直方图的面积为1,因此可以按原样使用kde。
对于计数图,直方图高度的总和将是给定数据的长度(每个数据项将恰好属于一个条形)。直方图的面积将是总高度乘以箱的宽度。 (当 bin 的宽度不相等时,调整 kde 会非常棘手)。
对于概率图,直方图高度的总和将为1(对于100 %)。总面积将是bin_width 乘以高度,因此等于bin_width。
这里有一些代码来解释发生了什么。它使用标准的 matplotlib 条形图、numpy 来计算 kde 的直方图和 scipy:
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
import numpy as np
data = [115, 127, 128, 145, 160]
bin_values, bin_edges = np.histogram(data, bins=4)
bin_width = bin_edges[1] - bin_edges[0]
total_area = bin_width * len(data)
kde = gaussian_kde(data)
x = np.linspace(bin_edges[0], bin_edges[-1], 200)
fig, axs = plt.subplots(ncols=3, figsize=(14, 3))
kws = {'align': 'edge', 'color': 'dodgerblue', 'alpha': 0.4, 'edgecolor': 'white'}
axs[0].bar(x=bin_edges[:-1], height=bin_values / total_area, width=bin_width, **kws)
axs[0].plot(x, kde(x), color='dodgerblue')
axs[0].set_ylabel('density')
axs[1].bar(x=bin_edges[:-1], height=bin_values / len(data), width=bin_width, **kws)
axs[1].plot(x, kde(x) * bin_width, color='dodgerblue')
axs[1].set_ylabel('probability')
axs[2].bar(x=bin_edges[:-1], height=bin_values, width=bin_width, **kws)
axs[2].plot(x, kde(x) * total_area, color='dodgerblue')
axs[2].set_ylabel('count')
plt.tight_layout()
plt.show()