使用plt.hist的density=True时直方图面积不为1的疑问
关于matplotlib plt.hist(density=True)的归一化误区解释
文档描述没错,问题出在你的计算方式理解有误。
核心逻辑:density=True 是让直方图总面积归一为1
当设置density=True时,matplotlib会调整每个直方图柱的高度,使得所有柱的高度 × 柱宽度的总和(即直方图的总面积)等于1,以此近似概率密度函数(PDF)。
你的计算错误点
- 直接用
sum(data1):这是对柱的高度求和,完全没考虑每个柱的宽度。bins数量变化时,柱宽度会变,高度也会跟着调整,所以这个求和结果肯定不会是1,还会随bins数量波动。 - 用
np.trapz(data1):你只传入了高度数据data1,np.trapz默认会用步长1计算积分,但实际每个柱的步长(宽度)是bin_edges[i+1] - bin_edges[i],不是1。这种情况下计算的积分自然不是总面积,结果也会随bins变化。
正确的计算方式
调用plt.hist时要捕获返回的三个值:柱高度、柱边缘坐标、绘图对象。然后通过以下两种方式计算总面积,结果会接近1:
import numpy as np import matplotlib.pyplot as plt test_dataset = np.random.normal(size=1000) # 获取直方图的高度、bin边缘 hist_heights, bin_edges, _ = plt.hist(test_dataset, bins=30, density=True) # 方法1:直接计算每个柱的面积并求和 total_area = np.sum(hist_heights * np.diff(bin_edges)) print("总面积(方法1):", total_area) # 方法2:用np.trapz,传入bin的中点作为x坐标 bin_midpoints = bin_edges[:-1] + np.diff(bin_edges)/2 total_area_trapz = np.trapz(hist_heights, bin_midpoints) print("总面积(方法2):", total_area_trapz)
不管bins数量怎么调整,只要数据量足够,这两个计算结果都会接近1,符合density=True的设计逻辑。
内容的提问来源于stack exchange,提问作者Curious
相关产品推荐
相关产品推荐

