📊 第5章 可视化数据分析图表
📄 一句话概括

直方图的横轴是「区间」,柱形图的横轴是「类别」。两者不能混。 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 秒实验

  1. 把 bins 改成 3 和 20,各数一遍每段人数,看哪一次形状最清楚。
  2. 把 YW 换成数学成绩,对比两张直方图的形状。
  3. 想一想:十个数据点画直方图,本来就有意义吗?

常见误区

  1. 把直方图当柱形图用:横轴放类别,两边的柱子贴死,读不出区间感。
  2. bins 用默认值不试:默认 10 段,对十个人来说太碎了。
  3. 以为直方图能看出离群值:极端值会缩成几乎看不见的小柱子。
  4. 纵轴是密度却按人数读:0.02 当成 0.02 个人。
自测三问(点开对答案) 1. 直方图的横轴和柱形图有什么不同? —— 直方图横轴是连续区间,柱子之间不留缝;柱形图横轴是离散类别,柱子分开站。 2. bins 设太大会出什么问题? —— 每段只剩一两个人,甚至出现空段,形状反而看不清。 3. 直方图和箱形图各擅长什么? —— 直方图看整体形状(单峰双峰、偏斜),箱形图看位置和离散程度(中位数、四分位、离群值)。

分布看完了。下一篇画占比:饼图和它的空心版环形图。

相关笔记