直方图的横轴是「区间」,柱形图的横轴是「类别」。两者不能混。 bins 是个要试的参数:太少了看不出形状,太多了每段只剩一两个人。 直方图看形状,箱形图看位置。同一列数,两张图各说一半。
上一篇的柱形图比的是类别。这一篇的直方图比的是「落在一个区间里有多少个」。 语文十个人分五段:2、1、2、2、3 人,加起来正好 10。
一、直方图分的是区间
把语文的十个数分成五段,数每段里落了几个人。
| 区间 | 人数 |
|---|---|
| 68 ~ 73 | 2 |
| 73 ~ 78 | 1 |
| 78 ~ 84 | 2 |
| 84 ~ 89 | 2 |
| 89 ~ 95 | 3 |
五段人数加起来 10,正好是总人数——这是直方图的自检办法。 对不上就说明分段的边界有重叠或漏空,或者数据里有缺失没说清。 直方图的横轴是区间,柱形图的横轴是类别。前者是连续的,后者是离散的。
二、bins 换一下,形状就变
bins=5 时,最高的那段 3 人,最矮的 1 人。 bins=10 时,最高的那段 2 人,最矮的那段 0 人——出现了空档。 同一个分布,段数一变,看起来「有没有空档」的结论就变了。
bins 是个要试的参数,没有标准答案。试两三个值,挑最能说明问题的那张。 经验:100 条以内用 5 到 10 段;上千条用 20 到 50 段。
三、直方图和箱形图的分工
直方图看形状:单峰还是双峰、偏左还是偏右、有没有缺口。 箱形图看位置:中位数在哪、四分位多宽、有没有离群点。 同一列数,两张图各说一半。要讲清楚就得两张都画。
只画直方图容易漏掉极端值——它们会缩成角落里一根几乎看不见的小柱子。
四、频数还是密度
纵轴是「人数」时叫频数直方图,这是默认。
density=True 之后纵轴变成概率密度,总面积等于 1。
这样就能和概率密度曲线叠在一起比,看「像不像正态分布」。
看纵轴就知道是哪一种。数在 0 到 10 之间是频数,0 到 1 之间是密度。
五、动手 Demo:直方图:看清一列数的形状
先算五段的人数并印成表,再对比 bins=5 和 bins=10 的差别。 最后画成图存下来。
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
YW = [88, 92, 75, 85, 90, 68, 95, 72, 83, 79]
CNT, EDGE = np.histogram(YW, bins=5)
for i in range(5):
print("%2d ~ %2d : %d 人" % (EDGE[i], EDGE[i + 1], CNT[i]))
print("合计 %d 人" % CNT.sum())
for b in (5, 10):
c, e = np.histogram(YW, bins=b)
print("bins=%2d 最高 %d 人 最矮 %d 人" % (b, c.max(), c.min()))
fig, ax = plt.subplots(figsize=(6, 4))
ax.hist(YW, bins=5, edgecolor="white")
ax.set_title("语文成绩分布")
ax.set_xlabel("分数")
ax.set_ylabel("人数")
fig.tight_layout()
fig.savefig("hist.png")
实跑输出:
--------------------------------------------------------------------
直方图:看清一列数的形状
--------------------------------------------------------------------
① 直方图分的是区间
--------------------------------------------------------------------
语文十个人,分 5 段:
| 区间 | 人数 |
|---|---:|
| 68 ~ 73 | 2 |
| 73 ~ 78 | 1 |
| 78 ~ 84 | 2 |
| 84 ~ 89 | 2 |
| 89 ~ 95 | 3 |
五段人数加起来 10,正好是总人数——这是直方图的自检办法。
! 直方图的横轴是「区间」,柱形图的横轴是「类别」。两者不能混。
② bins 换一下,形状就变
--------------------------------------------------------------------
bins=5 时,最高的那段有 3 人,最矮的那段有 1 人。
bins=10 时,最高的那段有 2 人,最矮的那段有 0 人。
段数太少看不出形状,段数太多每段只剩一两个人,也看不出形状。
经验:数据量 100 以内用 5 到 10 段;上千条用 20 到 50 段。
! bins 是个要试的参数,没有标准答案。试两三个值,挑最能说明问题的那张。
③ 直方图和箱形图的分工
--------------------------------------------------------------------
直方图看「形状」:单峰还是双峰、偏左还是偏右、有没有缺口。
箱形图看「位置」:中位数在哪、四分位多宽、有没有离群点。
同一列数,两张图各说一半。要讲清楚就得两张都画。
! 只画直方图容易漏掉极端值——它们会缩成角落里一根几乎看不见的小柱子。
④ 密度线:hist 加 kde
--------------------------------------------------------------------
把 hist 的 density 设成 True,纵轴就从「人数」变成「概率密度」。
这时候直方图的总面积等于 1,能直接和概率密度曲线叠在一起比。
! 纵轴是人数时叫频数直方图,是密度时叫密度直方图。看纵轴就知道是哪一种。
np.histogram 只算数不画图,返回「每段人数」和「段边界」两样东西。
段边界比段数多一个。5 段有 6 个边界,这是 +1 的关系。
30 秒实验
- 把 bins 改成 3 和 20,各数一遍每段人数,看哪一次形状最清楚。
- 把 YW 换成数学成绩,对比两张直方图的形状。
- 想一想:十个数据点画直方图,本来就有意义吗?
常见误区
- 把直方图当柱形图用:横轴放类别,两边的柱子贴死,读不出区间感。
- bins 用默认值不试:默认 10 段,对十个人来说太碎了。
- 以为直方图能看出离群值:极端值会缩成几乎看不见的小柱子。
- 纵轴是密度却按人数读:0.02 当成 0.02 个人。
自测三问(点开对答案)
1. 直方图的横轴和柱形图有什么不同? —— 直方图横轴是连续区间,柱子之间不留缝;柱形图横轴是离散类别,柱子分开站。 2. bins 设太大会出什么问题? —— 每段只剩一两个人,甚至出现空段,形状反而看不清。 3. 直方图和箱形图各擅长什么? —— 直方图看整体形状(单峰双峰、偏斜),箱形图看位置和离散程度(中位数、四分位、离群值)。分布看完了。下一篇画占比:饼图和它的空心版环形图。
- ☐ (本篇完,下一篇 5.8 饼形图与环形图)