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

热力图拿颜色当第三个维度,最适合一次扫一遍两两之间的关系。 vmin 和 vmax 必须固定,不然每张图各自动缩放,颜色没有可比性。 箱形图一次给五个数:最小值、Q1、中位数、Q3、最大值,还标出离群点。

📝 本章和前面几章的关系

上一篇看两个量的关系,这一篇看「一堆量两两之间的关系」,还有「几组数的分布」。 相关系数矩阵是 4 行 4 列,热力图是它最合适的画法。

一、相关系数矩阵

语文 数学 英语 总分
语文 1.000 0.573 0.788 0.897
数学 0.573 1.000 0.518 0.818
英语 0.788 0.518 1.000 0.884
总分 0.897 0.818 0.884 1.000

矩阵是对称的,对角线全是 1——自己和自己必然完全相关。 语文和总分 0.897、英语和总分 0.884、数学和总分 0.818。 三科彼此之间是 0.573、0.518、0.788,都比它们各自和总分的相关弱。

总分是三个相加出来的,它和每一科必然相关。这种自己造的列不该进相关分析。

二、热力图:颜色当第三维

ax.imshow(mat.values, cmap='RdYlGn', vmin=-1, vmax=1) 把矩阵画成色块。 vmin 和 vmax 固定成 -1 和 1,颜色才有绝对含义:深绿强正相关,深红强负相关。 不固定范围的话,每次自动缩放,两张热力图没法对比。

fig.colorbar(im, ax=ax) 加色标。没有色标,颜色就是纯装饰,读者只能猜。

三、箱形图:一次给五个数

箱子的上边是 Q3、下边是 Q1,中间那条线是中位数,两根须是范围。 须外面单独标出来的点是离群值。 语文:中位数 84.0、Q1 76.00、Q3 89.50,IQR 是 13.50。

箱形图一次说清「中间在哪、多宽、有没有离群」。比看十个数快得多。 它的盲区是看不出双峰——要判断形状还得回头画直方图。

四、两张图怎么配

图 横轴是什么 适合看什么
热力图 变量(行列都是) 两两之间的关系
箱形图 分组 每组内部的分布

热力图的行列都是变量,箱形图的横轴是分组。这是两者最容易混的地方。 前者回答「哪些量一起动」,后者回答「哪一组更齐、有没有异常」。

五、动手 Demo:热力图与箱形图

先算四列的相关系数矩阵并印出来,再画成热力图(固定 -1 到 1)。 最后画三科的箱形图,读一遍四分位。

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False

DF = pd.DataFrame({
    "语文": [88, 92, 75, 85, 90, 68, 95, 72, 83, 79],
    "数学": [92, 95, 68, 88, 73, 82, 91, 65, 86, 90],
    "英语": [85, 90, 80, 79, 95, 71, 88, 60, 84, 87],
})
DF["总分"] = DF[ ["语文", "数学", "英语"]].sum(axis=1)
C = DF.corr()
print(C.round(3).to_string())

fig, ax = plt.subplots(figsize=(5, 4))
im = ax.imshow(C.values, cmap="RdYlGn", vmin=-1, vmax=1)
ax.set_xticks(range(4))
ax.set_xticklabels(C.columns, rotation=45)
ax.set_yticks(range(4))
ax.set_yticklabels(C.index)
fig.colorbar(im, ax=ax)
fig.tight_layout()
fig.savefig("heat.png")

Q1 = np.percentile(DF["语文"], 25)
Q3 = np.percentile(DF["语文"], 75)
print("语文 中位数 %.1f  Q1 %.2f  Q3 %.2f  IQR %.2f"
      % (DF["语文"].median(), Q1, Q3, Q3 - Q1))

实跑输出:

--------------------------------------------------------------------
热力图与箱形图
--------------------------------------------------------------------

  ① 相关系数矩阵
  --------------------------------------------------------------------

| 行 | 语文 | 数学 | 英语 | 总分 |
|---|---:|---:|---:|---:|
| 语文 | 1.0 | 0.573 | 0.788 | 0.897 |
| 数学 | 0.573 | 1.0 | 0.518 | 0.818 |
| 英语 | 0.788 | 0.518 | 1.0 | 0.884 |
| 总分 | 0.897 | 0.818 | 0.884 | 1.0 |

  四列两两算相关,得到一个 4 行 4 列的对称矩阵,对角线全是 1。
  语文和总分 0.897,数学和总分 0.818,英语和总分 0.884。
  三科彼此之间是 0.573、0.518、0.788,都比它们各自和总分的相关弱。
  ! 总分是三个相加出来的,它和每一科都必然相关。这种「自己造的列」不该进相关分析。

  ② 热力图:颜色当第三个维度
  --------------------------------------------------------------------
  imshow 把矩阵画成色块,vmin 和 vmax 固定成 -1 和 1,颜色才有可比性。
  不固定范围的话,每次自动缩放,两张热力图没法对比。
  ! 热力图必须配 colorbar。没有色标,颜色就是纯装饰,读者只能猜。

  ③ 箱形图:一次给五个数
  --------------------------------------------------------------------
  箱子上下边是 Q3 和 Q1,中间那条线是中位数,两根须是范围,点出去的是离群值。
  语文中位数 84.0、Q1 76.00、Q3 89.50。
  ! 箱形图一次说清「中间在哪、多宽、有没有离群」。比看十个数快得多。

  ④ 两张图怎么配
  --------------------------------------------------------------------
  热力图看「两两之间的关系」,适合一次扫一遍所有配对。
  箱形图看「一组数的分布」,适合横向比较几组。
  热力图的行列都是变量,箱形图的横轴是分组。这是两者最容易混的地方。
  ! 箱形图看不出双峰。要判断形状还得回头画直方图。

DF[ ["语文", "数学", "英语"]].sum(axis=1) 是按行加,总分那一列就这么来的。 corr() 会自动跳过非数值列。姓名、班级这类列不会进矩阵,也不会报错。

30 秒实验

  1. 把 vmin 和 vmax 去掉,看颜色怎么变(再画第二张对比)。
  2. 把 boxplot 里的三科换成「一班」和「二班」的总分,看两个箱子谁更宽。
  3. 想一想:为什么总分那一列不该放进相关分析?

常见误区

  1. 热力图不固定 vmin/vmax:每张图各自动缩放,颜色没法对比。
  2. 热力图不配 colorbar:颜色没有刻度,读者只能猜。
  3. 把自造的列放进相关分析:总分和每科都强相关,那是加法造出来的。
  4. 用箱形图判断双峰:箱形图只给五个数,看不出形状。
  5. 对整个 DF 做按行求和:碰到姓名这类字符串列会报 TypeError,得先挑出数值列。
自测三问(点开对答案) 1. 热力图的 vmin 和 vmax 为什么要固定? —— 固定之后颜色才有绝对含义,不同图之间才能对比。不固定则每张图各自缩放。 2. 箱形图那五个数分别是什么? —— 最小值、Q1、中位数、Q3、最大值。须外的点单独标出来是离群值。 3. 为什么「总分」不适合进相关矩阵? —— 它是三科相加造出来的列,和每一科都必然强相关,这种相关没有信息量。

二维图都会了。下一篇上三维:3D 图、多子图,还有保存格式的选择。

相关笔记