3.3 高级统计图形 本节摘要:前面画的折线、柱状、散点图,回答的是"趋势、大小、关系"这类直观问题;这一节我们换一批更"统计"的图形——直方图、箱线图、小提琴图、热力图、散点矩阵。它们各有各的强项:直方图看分布形状,箱线图看五数概括和异常值,小提琴图把密度也画出来,热力图读相关矩阵,散点矩阵一次看遍多变量。本节逐个讲清"这张图回答什么问题、关键参数是什么、什么时候该用",让你在探索数据时能对症下药。 阅读收获 阅读完本节,你应当能够: 用直方图判断数据分布的形状,并理解 bins 对图形的影响。 读懂箱线图的箱体、须、中位线和异常点,说出五数概括。 说清小提琴图比箱线图多提供了什么信息。 用热力图读取相关矩阵,识别强相关和弱相关的变量对。 用散点矩阵快速浏览多变量之间的两两关系。
本节摘要:前面画的折线、柱状、散点图,回答的是"趋势、大小、关系"这类直观问题;这一节我们换一批更"统计"的图形——直方图、箱线图、小提琴图、热力图、散点矩阵。它们各有各的强项:直方图看分布形状,箱线图看五数概括和异常值,小提琴图把密度也画出来,热力图读相关矩阵,散点矩阵一次看遍多变量。本节逐个讲清"这张图回答什么问题、关键参数是什么、什么时候该用",让你在探索数据时能对症下药。
阅读完本节,你应当能够:
直方图是最基础的统计图形,却也是最容易被轻视的一张。它把数据切成一堆连续的区间,统计每个区间里有多少个点,画成柱状。这一眼,就能看出数据是集中在中间、还是拖了尾巴、还是双峰。
Matplotlib 画直方图就一行:
import matplotlib.pyplot as plt import numpy as np data = np.random.randn(1000) plt.hist(data, bins=30, edgecolor='black') plt.show()
这里唯一的讲究是 bins。bins 太小,柱子太粗,分布细节被糊成几坨;bins 太大,柱子太细,噪声被放大,看起来像锯齿。没有放之四海皆准的值,一般从 20 到 50 之间试起,再看着图微调。数据量越大,bins 可以越细。
直方图能回答三个问题:数据像不像正态分布、有没有拖尾的偏态、是不是藏着多个峰。多个峰尤其值得警惕——它往往意味着数据来自不同的子群体,比如把两个城市的房价画进一张直方图,可能就会出现两个峰。
比较两组数据的分布时,有两种画法:要么把两组直方图叠在一起,要么并排放。叠放要记得设透明度,否则前面的柱子把后面的遮住;并排更直观,但组数多了会拥挤。还有一个参数 density,把它设成 True,纵轴就从"个数"变成"比例",这样两组样本量不一样时也能公平比较——不设的话,样本多的那组柱子天然就高,比的是个数而不是形状。
⚠️ 直方图对 bins 很敏感,同一份数据用不同 bins 可能给出完全不同的"故事"。下结论前,多换几个 bins 看看,别让一个随意的分箱数绑架了你的判断。
箱线图是"分布摘要"的极简表达。它用一个箱子和两根须,把五数概括——最小值、下四分位数、中位数、上四分位数、最大值——画进一张图里。
箱子的上下边是下四分位数和上四分位数,中间那根线是中位数,箱子里装着中间 50% 的数据。两根须从箱子伸出去,通常延伸到 1.5 倍四分位距的范围内,超出须的点单独画成点,那就是异常值。
groups = [np.random.normal(0, 1, 100), np.random.normal(2, 1.5, 100), np.random.uniform(-1, 3, 100)] plt.boxplot(groups, labels=['甲', '乙', '丙'], patch_artist=True) plt.show()
箱线图最大的本事是比较。把几组数据并排画成几个箱子,一眼就能看出谁的中位数高、谁的分布散、谁出了异常值。三个箱子一摆,"甲组整体偏低、丙组离散度大"这种结论直接跳出来。
读箱线图要抓住三个信号:箱子位置代表中心,箱子长短代表离散,须外的点代表异常。别只盯着中位数那根线,箱子本身的信息量一点不少。
箱线图还有两个常用变体。一个是水平方向,把 labels 那几组数据换到纵轴上,组名特别长时水平摆更好读。另一个是带缺口的箱线图,缺口画在中位数附近,表示中位数的置信区间——两个箱子的缺口不重叠,往往意味着两组的中位数差异是显著的。日常探索用基础箱线图就够,缺口版留给需要"下统计结论"的场合。
箱线图把分布压成了五个数,信息浓缩,但也丢了形状。两个分布可以五数概括一模一样,形状却差很远——一个像倒扣的碗,一个双峰。这时候小提琴图登场了。
小提琴图在箱线图的基础上,把核密度估计画成两侧对称的"琴身":某处数据越密集,琴身越宽。于是你既能读到箱线图的五数概括,又能看到分布到底长什么样、有没有多峰、尾巴拖多长。它比箱线图信息更足,代价是看起来稍复杂。
Matplotlib 较新的版本自带 violinplot,但更常见的做法是借 Seaborn 的封装:
import seaborn as sns sns.violinplot(data=groups, inner='quart') plt.show()
inner 参数控制琴身里放什么:quart 放四分位线,box 放一个小箱线图,point 只放点。这个参数决定了小提琴图"箱线图化"的程度。
💡 什么时候从箱线图升级到小提琴图?当样本量够大、你又怀疑分布不是简单的单峰时。箱线图适合快速扫一眼,小提琴图适合深挖形状。样本太少时,小提琴的密度估计反而不可靠,这时老老实实用箱线图。
热力图用颜色深浅表示数值大小,最适合读矩阵。在数据分析里,它最常见的用途是画相关矩阵——把一堆变量两两之间的相关系数摆成一张方阵,颜色从深蓝到深红,正相关偏红、负相关偏蓝、接近零偏白。
Matplotlib 用 imshow 就能画,或者直接借 Seaborn 的 heatmap 一步到位:
import seaborn as sns corr = df.corr() # 算相关矩阵 sns.heatmap(corr, annot=True, cmap='coolwarm', fmt='.2f') plt.show()
annot 控制要不要在每个格子里写数值,cmap 控制色板,coolwarm 是"冷蓝、白、暖红"的双向色板,特别适合有正有负的相关系数。
不用 Seaborn,纯 Matplotlib 的 imshow 也能画热力图:先把矩阵传给 imshow,再配一个 colorbar 颜色条。区别在于 Seaborn 帮你把"标数值、画格线、调刻度"这些琐事一步做了,imshow 则要你手动设置刻度标签。结论是:相关矩阵这种标准场景直接用 Seaborn,要完全掌控每个格子时再退回 imshow。
读热力图的技巧是"先看对角线,再看最红和最蓝的格子"。对角线永远是 1(自己和自己完全相关),真正有价值的是对角线之外那些特别红的格子——它们标出强相关变量对,可能是冗余特征,也可能是你要找的线索。找到强相关之后,再回到散点图去验证关系长什么样,这是热力图和散点图的标准配合。
⚠️ 相关不等于因果,这句话在热力图上尤其要记牢。两个变量相关系数很高,可能只是它们同时受第三个变量驱动。热力图负责"发现嫌疑",不负责"定罪",定性结论要靠业务理解和进一步分析。
当你有四五个数值变量,想一次看全它们两两之间的关系,散点矩阵是最省事的选择。它把变量排成行列,每个格子画一对变量的散点图,对角线画每个变量自己的分布。一眼扫过去,谁和谁正相关、谁和谁是独立的、哪个变量有离群点,全都铺在面前。
import seaborn as sns sns.pairplot(df) plt.show()
散点矩阵的强项是"地毯式扫描",弱项是变量一多就撑爆——十个变量就是一百个格子,看不过来也画不动。所以它适合变量数在五六个以内的探索,再多就该先用相关矩阵筛一遍,只对强相关的几对画散点图。
看散点矩阵的顺序是:先扫对角线看每个变量的分布,再扫非对角线找"有明显形状"的格子——线性、曲线、分簇、离群点都算形状。找到有趣的格子,再单独放大那一对去细看。这个顺序能保证你不会被满屏的点晃花了眼,也不会漏掉重要的相关对。
严格说,等高线图和三维曲面图不算"统计图形",但它们在数据探索里很常用,值得带上。等高线图用一圈圈等值线表示二维平面上的"高度",像地图的等高线表示海拔;三维曲面图则直接把那张曲面立起来。
x = np.linspace(-3, 3, 100) y = np.linspace(-3, 3, 100) X, Y = np.meshgrid(x, y) Z = np.exp(-(X**2 + Y**2)) plt.contourf(X, Y, Z, cmap='viridis') plt.colorbar() plt.show()
这两个图的共同前提是 meshgrid——上一节造二维网格那套。它们适合画数学函数、物理场、以及散点图的密度轮廓。把一堆散点做成二维密度再画等高线,是"散点太多看不清"时的一种降噪手段。
等高线本身也有两个层次:contour 只画一圈圈等值线,contourf 把线之间的区域用颜色填满。前者适合标注具体数值,后者适合看整体趋势。三维曲面图则用 plot_surface 把 Z 立起来,颜色同样由 cmap 控制,适合展示曲面的起伏。这两类图在正式报告里用得不多,但在函数拟合、地理和密度分析里是主力。
这一节一口气见了六七种图,把它们放一起对个表,选起来就不纠结:
| 图形 | 回答的问题 | 关键点 | 常见误用 |
|---|---|---|---|
| 直方图 | 分布长什么样 | bins 分箱 | 用随意 bins 下结论 |
| 箱线图 | 中心、离散、异常值 | 五数概括 | 忽略样本量差异 |
| 小提琴图 | 分布的密度形状 | 核密度估计 | 小样本强行用 |
| 热力图 | 矩阵里的相关关系 | 色板与数值标注 | 把相关当因果 |
| 散点矩阵 | 多变量两两关系 | 变量数控制 | 变量太多硬画 |
| 等高线图 | 二维函数或密度 | meshgrid 网格 | 与散点混淆 |
选图的心法其实就一条:先问"我要回答什么问题",再回头套这张表。问题定对了,图多半不会选错。这张表也不用背,用多了自然记住——每种图对应一种"数据的问法",问法记住了,图就记住了。
💡 这批统计图形有个共同的隐性前提:样本量。样本太少时,直方图的形状、小提琴的密度、热力图的相关都不可靠。画之前先问一句"我有多少个点",几十个点的数据,别指望小提琴图告诉你多少真相。
下一节我们把视角从"画什么图"拉到"图怎么画才对",用一套可视化原则给前面所有的图做一次质检。