2.2 核密度与经验分布


文档摘要

2.2 核密度与经验分布 kdeplot 用平滑曲线估计概率密度,形态直觉最好;ecdfplot 画经验累积分布,读数精确且无需任何超参数;rugplot 在轴边原位标记每个观测,是识别样本量与离群点的显微镜。 2.1 的直方图依赖分箱,换个 bins 数结论就可能晃动。本节拆两件不依赖分箱(或依赖更少)的工具,它们和 2.1 一起构成分布三板斧。 核密度:带宽决定一切 核密度的原理一句话:每个观测点贡献一个小钟形,全部叠起来再归一化。带宽就是这个钟形的胖瘦。太瘦,单点噪声各自成峰;太胖,真实的双峰结构被焊死在一起。iris 的花瓣长度存在真实的双峰(setosa 与其他两物种分开),这个结构只有带宽合适时才看得见——形态结论必须先过带宽稳定性检查,这是核密度使用的铁律。

2.2 核密度与经验分布

kdeplot 用平滑曲线估计概率密度,形态直觉最好;ecdfplot 画经验累积分布,读数精确且无需任何超参数;rugplot 在轴边原位标记每个观测,是识别样本量与离群点的显微镜。

2.1 的直方图依赖分箱,换个 bins 数结论就可能晃动。本节拆两件不依赖分箱(或依赖更少)的工具,它们和 2.1 一起构成分布三板斧。

核密度:带宽决定一切

import seaborn as sns import matplotlib.pyplot as plt iris = sns.load_dataset('iris') # 带宽扫描:bw_adjust 是默认带宽的缩放系数 fig, axes = plt.subplots(1, 3, figsize=(13, 3.5)) for ax, bw in zip(axes, [0.25, 1, 4]): sns.kdeplot(data=iris, x='petal_length', bw_adjust=bw, fill=True, ax=ax) ax.set_title(f'bw_adjust = {bw}') plt.show() # 输出说明:0.25 时曲线出现多个尖峰(把噪声当结构);4 时曲线过度平滑 # (鸢尾花两个明显的物种簇被抹成一个宽包);1 附近才能看到"双峰"这一关键形态

核密度的原理一句话:每个观测点贡献一个小钟形,全部叠起来再归一化。带宽就是这个钟形的胖瘦。太瘦,单点噪声各自成峰;太胖,真实的双峰结构被焊死在一起。iris 的花瓣长度存在真实的双峰(setosa 与其他两物种分开),这个结构只有带宽合适时才看得见——形态结论必须先过带宽稳定性检查,这是核密度使用的铁律。

# 按物种分组后,双峰之谜解开:每个物种内部各自单峰 ax = sns.kdeplot(data=iris, x='petal_length', hue='species', fill=True, alpha=0.3) # 输出说明:setosa 独占低值区,versicolor 与 virginica 部分重叠—— # 这条信息直接指向第 8 章分类任务里 setosa 几乎可完美分出、后两者边界模糊

fill=True 填充曲线下方,多组比较时记得配 alpha,否则后面的组会被盖住。cut 参数控制曲线延伸范围:默认 3 会把曲线画到数据实际范围之外,界面截图或严格报告里设 cut=0 更稳妥。

经验累积分布:最被低估的图

# ecdfplot:每个台阶表示"小于等于该值的观测占比" ax = sns.ecdfplot(data=tips, x='total_bill') ax.axhline(0.5, color='gray', linestyle='--', linewidth=1) ax.set_xlabel('总消费(美元)') ax.set_ylabel('累积占比') # 输出说明:曲线与 0.5 虚线的交点横坐标即中位数,约 17.8 美元; # 想读"低于 25 美元的账单占多少",直接在 x=25 处读高度即可,误差只在样本级

ecdf 的三个直方图给不了的优势:没有超参数(不分箱、不选带宽);任意分位精确可读;多组比较时曲线的垂直错位直接对应概率差异。代价是形态直觉弱——它不适合一眼判断"有几个峰"。所以我的习惯是:探索阶段 kde 看形态,汇报阶段 ecdf 给精确数字。

# 按星期分组的累积分布对比 ax = sns.ecdfplot(data=tips, x='total_bill', hue='day') # 输出说明:曲线整体靠左的星期(如 Thursday)账单偏小; # Sunday 的曲线在 20 美元以后才追上来,说明它的大额账单占比更高

rugplot:叠加在任意分布图上

# 三层叠加:密度曲线 + 地毯 + 中位数参考线 ax = sns.kdeplot(data=tips, x='total_bill', fill=True, alpha=0.25) sns.rugplot(data=tips, x='total_bill', ax=ax, height=0.04, color='dimgray') ax.axvline(tips['total_bill'].median(), color='crimson', linestyle=':') # rug 的每根短竖线就是一个真实观测: # 竖线密集处曲线的峰有数据支撑,曲线有峰但竖线稀疏处就是带宽画出来的假象

rug 是分布图的"证词层"。核密度可能撒谎(带宽不当),直方图可能撒谎(分箱不当),但地毯图只陈述事实:有多少个点、落在哪里。样本量超过几千时 rug 会糊成实心条,那时它反而成了样本量的诚实指示。

分组密度的归一化陷阱

分组 kde 还有一个高频误读:默认 common_norm=True 时所有组共享同一次归一化,概率总量按各组观测数分配——两组样本量悬殊时(比如一组几十条、一组几千条),小组曲线会被整体压得几乎贴地,读者会误判该组数据稀薄甚至分布平坦。想比较各组自身的形状,设 common_norm=False 让每组各自归一,形状对比才公平;想表达谁占总量多少,才保留默认。另一个易错点是 NaN:kdeplot 遇到缺失值会静默丢弃整行,不抛错不出警告,某组缺失集中时就会出现这组的曲线凭空消失的现象——画图前先对映射列 dropna,是分布家族的标准前置动作。长尾数据(收入、房价这类跨数量级的形状)直接画 kde,尾部会把主峰压成一根针,配 log_scale=True 换对数刻度后主结构才回到视野中央,该参数与 histplot 的同名参数语义一致,两节的经验可以直接互通。

选型速查

工具 回答的问题 超参数 典型风险
histplot 各区间落了多少点 分箱 分箱敏感
kdeplot 分布形状如何、峰在哪 带宽 平滑出假峰或抹掉真峰
ecdfplot 低于某值的占比多大 形态直觉弱
rugplot 观测原位在哪、多密 大样本糊成条

💡 关键直觉:把 kde 当"形状镜头"、ecdf 当"读数卡尺"、rug 当"证词记录",三者互相校验,分布结论就很难被超参数骗到。

02-02-fig01

本节要点回顾

  • 带宽是 kde 唯一要害:汇报前用 bw_adjust 扫 0.25、1、4 验证峰的稳定性;
  • cut=0 防越界:曲线不延伸到数据范围之外;
  • ecdf 无超参数:中位数、分位、占比精确可读,多组比较看垂直错位;
  • rug 是事实层:曲线与竖线互相印证,防平滑假象;
  • 双峰背后常有隐藏分组:iris 的例子说明先拆组再下形态结论。

单变量分布至此拆完。下一节把第二个变量引进来,看 displot 如何分面、jointplot 如何把联合与边缘装进一张图。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U