如何用Matplotlib将直方图归一化至柱高最大值?
直方图归一化:将柱高除以最大柱高的实现
你需要基于pandas单列数据绘制多组直方图,由于各组数据长度不同,要实现将每个柱高除以本组最大柱高的归一化(不用matplotlib内置的density参数),同时希望调整分箱数后,原始直方图和归一化直方图能同步更新。
先搞懂plt.hist的返回值
plt.hist()返回三个核心值:
n:numpy数组,每个元素对应一个分箱的样本数量(也就是直方图的柱高)bins:numpy数组,存储分箱的边界值,长度比n多1(比如50个分箱对应51个边界)patches:每个柱对应的图形对象,一般场景下用不到
你之前的代码错误在于:把原始数据除以max(n),这会直接改变数据的分布,完全不是对柱高的归一化操作。下面是正确的实现步骤:
正确实现流程
- 提取柱高与分箱边界:先调用
plt.hist()获取原始直方图的柱高n和分箱bins - 归一化柱高:将所有柱高除以本组的最大柱高
- 绘制归一化直方图:用
plt.bar()基于已有的分箱和归一化后的柱高绘图(因为plt.hist()是基于原始数据统计,我们已经有统计结果,用bar更直接准确)
完整可复用代码
import pandas as pd import matplotlib.pyplot as plt import numpy as np # 示例数据(替换成你的DataFrame) df = pd.DataFrame({'values': np.random.randn(1000)}) # 定义分箱数,调整这个值就能同步更新两张图 bin_num = 50 # 1. 绘制原始直方图并提取统计结果 plt.figure(figsize=(12, 5)) plt.subplot(1, 2, 1) n, bins, patches = plt.hist(df['values'], bins=bin_num) plt.title('原始直方图') plt.xlabel('数值') plt.ylabel('样本数量') # 2. 计算归一化柱高 n_normalized = n / np.max(n) # 计算每个分箱的宽度 bin_width = bins[1] - bins[0] # 3. 绘制归一化后的直方图 plt.subplot(1, 2, 2) # 用bar绘图,x坐标取分箱左边界+半宽让柱居中,宽度设为bin_width plt.bar(bins[:-1] + bin_width/2, n_normalized, width=bin_width) plt.title('归一化直方图(柱高/最大柱高)') plt.xlabel('数值') plt.ylabel('归一化柱高') plt.tight_layout() plt.show()
关键说明
- 调整
bin_num的值,原始图和归一化图的分箱数会同步更新 - 归一化仅针对柱高,完全保留原始数据的分箱区间,确保不同组直方图的横轴可比
- 用
plt.bar()而非再次调用plt.hist(),因为我们已经有了统计好的柱高,直接绘图更高效且避免重复统计
内容的提问来源于stack exchange,提问作者etruhart314
相关产品推荐
相关产品推荐

