skew()返回无偏估计的偏度(三阶中心矩标准化值),kurtosis()默认返回超额峰度(excess kurtosis,即峰度减3);二者均为描述统计量,非正态性检验结果。

skew() 和 kurt() 返回的是什么,不是“正态性检验结果”
很多人一看到 scipy.stats.skew() 和 scipy.stats.kurtosis()(注意不是 kurt())就以为返回值直接对应“是否正态”,其实不是。skew() 返回的是三阶中心矩标准化后的偏度估计(无偏估计默认开启),kurtosis() 默认返回的是**峰度减去3**(即 excess kurtosis),也就是以正态分布为基准的相对峰度。这意味着:正态分布的 skew() ≈ 0,kurtosis() ≈ 0 —— 不是 3。
- 用
scipy.stats.kurtosis(data, fisher=True)才是默认行为(excess);设fisher=False才返回原始峰度(正态下≈3) -
skew()默认用bias=False做无偏校正,小样本下更稳;设bias=True则是教科书定义的 m₃/m₂^(3/2) - 它们只是描述统计量,不能代替
scipy.stats.shapiro()或scipy.stats.normaltest()做假设检验
为什么 pandas 的 .skew() 和 scipy.stats.skew() 结果不一样
pandas 的 Series.skew() 和 DataFrame.skew() 默认不做无偏校正(bias=True),而 scipy.stats.skew() 默认做(bias=False)。小样本(n
- 统一做法:都显式指定
bias=False(推荐),尤其做跨库对比或复现论文时 - pandas 不支持
fisher参数,它的.kurtosis()等价于scipy.stats.kurtosis(..., fisher=True) - 注意 NaN 处理:pandas 默认
skipna=True,scipy 默认报错,务必先用dropna()或传nan_policy='omit'
skew() 接近 0 但直方图明显右偏?可能是样本太小或离群值干扰
偏度对极端值极度敏感。一个远在 5σ 外的离群点,就能让 skew() 从 0.1 拉到 1.5,但直方图肉眼未必能立刻识别——尤其当 bin 数少或范围没调好时。
- 先用
plt.boxplot()或data.describe()快速扫一眼min/max/75%差距 - 试试去掉 top/bottom 1% 数据再算
skew(),看数值是否回落到合理区间(如 |skew| - 对数变换后重算:若
skew(np.log1p(data))显著降低,说明原数据右偏且适合 log 处理
用 kurtosis() 判断“尖峰厚尾”要小心平台效应和样本量
样本量低于 50 时,kurtosis() 方差极大,可能把正态样本算出 ±5 的峰度;而样本量超 500 后,轻微厚尾(如 t(8) 分布)也能稳定检出 >0.5 的 excess kurtosis。
立即学习“Python免费学习笔记(深入)”;
- 别只看绝对值:|kurtosis| > 1 在 n>200 时才较有参考意义;n
- 平台数据常见“伪高峰”:大量零值堆叠在左侧(如用户停留时长),导致
kurtosis虚高,此时应结合value_counts(normalize=True).iloc[0]看零值占比 - 想对比不同量纲变量的峰态?先标准化(
z = (x - x.mean()) / x.std()),再算kurtosis(z),否则无意义
偏度和峰度不是开关按钮,它们是放大镜——放得越大,越要看清背后的数据生成逻辑和采样条件。直接拿两个数字去卡“正态性阈值”,八成会误伤。


















