商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Python怎么画直方图_hist()频数分布与bins区间数量调整

Python怎么画直方图_hist()频数分布与bins区间数量调整

  发布于2026-07-19 阅读(0)

扫一扫,手机访问

画直方图的时候,最让人头疼的往往是柱子数量——要么糊成一团黑块,根本看不出分布;要么碎成细线,信息全被噪音淹没。问题本质出在 bins 参数上。默认值(比如 10'auto')只适合简单数据,实际场景里几乎都得手动调。

怎么调?两种方式最常用:一个是直接给整数,比如 bins=20,强制分 20 组;另一个是传数组,比如 np.arange(0, 101, 5),明确指定每个区间的边界。Matplotlib 也支持 'fd''scott''sturges' 这类字符串自动计算,但千万别无脑信——尤其是数据有大量重复值或长尾的时候,'sturges 经常严重低估 bins 数量,直接导致柱子太少。数据量小的(比如几百个),bins=10 可能还嫌密;数据量大的(超过一万),bins=50 可能都不够,得试到柱子边缘清晰、不锯齿也不重叠才算到位。

Python怎么画直方图_hist()频数分布与bins区间数量调整

plt.hist() 画出来的直方图柱子太少或太多,怎么调 bins

这个问题的根源其实就是 bins 设置不合理。很多新手一上来就 plt.hist(data),结果要么柱子太宽丢失细节,要么太窄全是锯齿。记住:bins 可以是整数(比如 20),表示强制分 20 组;也可以是数组(比如 np.arange(0, 101, 5)),明确指定每个区间的边界。用 'fd''scott''sturges' 这类字符串也行,但别盲目依赖自动算法——尤其当数据有大量重复值或长尾时,'sturges' 常常低估 bins 数量。数据量小(<1000),bins=10 可能过密;数据量大(>10000),bins=50 可能还不够,得试到柱子边缘清晰、不锯齿也不重叠为止。

想看频数(count)还是概率密度(density),关键看 density 参数

很多人调完 bins 发现纵轴数字看不懂:明明总共 1000 个数,最高柱子却标着 0.03?这大概率是误开了 density=True。做探索性分析、想看看“有多少个”的时候,用默认的频数模式(density=False)就够了;只有当你需要和概率密度曲线(比如正态分布 PDF)做对比,或者做拟合分布可视化时,才该设 density=True

  • density=False(默认):纵轴是落入该 bin 的样本个数,所有柱子面积之和 = 总样本数。
  • density=True:纵轴变成概率密度,所有柱子面积之和 = 1,此时高度 = 频数 / (总样本数 × bin 宽度)。
  • 注意:一旦设了 density=True,就不能直接和原始频数曲线叠在一起画,否则尺度错乱。

横坐标范围不对、bin 边界不齐整,检查 range 和 bins 类型配合

比如数据是 [1.2, 1.8, 2.1, ..., 9.7],但直方图从 0 开始、到 10 结束,且 bin 边界是 0.0, 1.0, 2.0...——这种“人为对齐”会让第一组/最后一组空着,或者把本该在一个 bin 的值劈开。常见现象:左右留白过大、某些 bin 明明有数据却显示为 0、柱子宽度不一致(尤其用了非等距 bins 数组时)。

  • range=(min_val, max_val) 可以限定横轴范围,但不会改变 bin 划分逻辑;真正控制划分的是 bins
  • 想要 bin 边界整齐(比如都落在整数上),推荐显式传入 bins=np.arange(start, stop+step, step),而不是只靠 range + 整数 bins
  • 如果数据含异常值(比如一个 1000 混在一堆 1~10 的数里),先 data = data[data < 100] 截断,再画图,否则 range 被拉长,bins 全部被稀释。

和 pandas hist() 混用时,bins 行为不一致容易踩坑

Pandas 的 Series.hist() 底层调用的就是 matplotlib.pyplot.hist(),但参数透传过程中有隐式转换——最典型的是 bins 为字符串时(如 'auto'),pandas 会先调 np.histogram_bin_edges() 算一次,再喂给 matplotlib,结果可能和你直接调 plt.hist(..., bins='auto') 不一样。快速探索用 df['col'].hist() 没问题;但需要复现、调试或和模型输出对齐时,务必切回原生 plt.hist() 并显式传参。

  • Pandas 的 hist() 不支持 density 参数,要用 weights 手动换算(比如 weights=np.ones(len(data))/len(data))模拟 density 效果。
  • 同一份数据,plt.hist(data, bins=20)pd.Series(data).hist(bins=20) 柱子位置和高度几乎一样;但换成 bins='sturges' 就可能差 2–3 个 bin。
  • 如果你在 Jupyter 里先跑 df.hist() 再跑 plt.hist(),记得加 plt.figure() 新建画布,否则两张图叠在一起,bins 设置互相干扰。

事情说清了就结束。真正难的不是调出一张“看起来对”的直方图,而是每次换数据都要重新判断:这组数据有没有离群点?要不要截断?bin 宽度该不该随数据范围缩放?这些没法写成固定参数,只能看图说话。

本文转载于:https://www.php.cn/faq/2314487.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注