如何让Python绘制的直方图百分比总和达到100%
问题根因
density=True参数会让plt.hist()返回概率密度值,而非分箱事件占比。概率密度的计算逻辑为分箱内事件占比 / 分箱宽度,只有所有分箱的「密度值 * 分箱宽度」求和才等于1(对应100%)。直接将密度值按百分比格式渲染,总和会远小于100%,和你观测到的总和约3%的现象完全匹配。
通用适配方案
采用权重法实现,无需依赖density参数,对任意一维输入数组、任意分箱规则都生效,所有分箱占比求和固定为100%:
- 核心逻辑:给每个样本设置等权重
1/总样本量,所有样本权重和为1,此时每个分箱的柱高直接对应该分箱的事件占比 - 直接替换原有绘图逻辑即可,不需要额外调整分箱、坐标轴格式配置
修正后可直接运行的代码:
import matplotlib.pyplot as plt from matplotlib.ticker import PercentFormatter import numpy as np plt.gca().yaxis.set_major_formatter(PercentFormatter(1)) data = np.array([0,9,78,6,44,23,88,77,12,29]) length_of_data = len(data) # 样本总长度 bins = int(np.sqrt(length_of_data)) # 分箱数量 # 核心修正:设置每个样本的权重,所有权重求和为1 weights = np.ones(length_of_data) / length_of_data plt.title('Histogram') plt.ylabel('Percentage Of Events') plt.xlabel('bins') # 传入weights参数,移除density=True配置 plt.hist(data, bins=bins, weights=weights) plt.show() # 校验占比总和 bin_counts, _ = np.histogram(data, bins=bins, weights=weights) print(f"分箱数量:{bins},所有分箱占比总和:{bin_counts.sum():.2%}")
运行后控制台会输出占比总和为100%,图中柱高对应各分箱的事件占比,累加和完全符合预期。如果需要更换输入数组,直接替换data变量的内容即可,不需要修改其他逻辑。
内容的提问来源于stack exchange,提问作者Logan
相关产品推荐
相关产品推荐

