如何对Matplotlib直方图中的概率分布值进行归一化处理?
同图绘制归一化累积与非累积直方图的解决方案
问题原因
你当前使用density=True参数得到的是概率密度直方图,该模式下要求的是所有bin的面积总和为1,而非bin高度≤1。当bin宽度较小时,概率密度 = 单bin频率 / bin宽度的计算结果自然会出现大于1的情况,这是非累积曲线y轴超标的核心原因。
解决方案
如果你需要让累积、非累积曲线共用0~1范围的y轴,可以将非累积直方图改为频率归一化,即单bin数值为「该bin样本数 / 总样本数」,所有非累积bin高度之和为1,和累积分布的y轴范围完全匹配。
实现时可以通过weights参数给每个样本设置统一权重1/总样本数,同时关闭density参数即可,修改后可运行代码如下:
import matplotlib.pyplot as plt n_bins = 20 x = [ 0.0051055006412772065, 0.09770815865459548, 0.20666651037049322, 0.5433266733820051, 0.5717169069724539, 0.5421114013759187, 0.4994941193115986, 0.4391978276380223, 0.3673067648294034, 0.3150259778098451, 0.4072059689437963, 0.5781929593356039, 0.6494934859266276, 0.620882081680377, 0.5845829440637116, 0.515705471234385] # 统一设置每个样本的权重为1/总样本数,统计结果直接为频率 weights = [1 / len(x)] * len(x) fig, ax = plt.subplots(figsize=(10, 5)) # 绘制累积分布 n, bins, patches = ax.hist(x, n_bins, weights=weights, stacked=True, histtype='step', cumulative=True, label='Empirical cumulative') # 绘制非累积分布 ax.hist(x, bins=bins, weights=weights, stacked=True, histtype='step', cumulative=False, label='Empirical non-cumulative') ax.legend() plt.show()
可选方案(保留概率密度)
如果你确实需要保留非累积的概率密度含义,可以设置双y轴分别展示两个曲线:左侧y轴对应累积分布(范围0~1),右侧y轴对应非累积概率密度,两者互不干扰。
内容的提问来源于stack exchange,提问作者Fluxy
相关产品推荐
相关产品推荐

