Shapiro检验仅适用于n<5000的小样本,p>0.05才勉强接受正态;Q-Q图需加line='45'参考线并结合直方图判断偏离;极值处理应据偏度选择IQR法而非简单分位截断。

用 scipy.stats.shapiro 检验小样本正态性,但别超 5000 个点
小样本(n shapiro 最可靠,p 值 > 0.05 才算勉强接受正态;超过 5000 个点它会直接报错 ValueError: Sample size must be less than 5000。这不是限制你数据量,是算法本身对大样本不敏感——此时 p 值极容易显著(
- 替代方案:n > 50 且 scipy.stats.kstest(需指定
cdf='norm')或scipy.stats.anderson(返回临界值表,比单个 p 值更稳) -
kstest要求先标准化数据:stats.kstest((x - x.mean()) / x.std(), 'norm'),漏这步结果完全不可信 - 注意
anderson的返回值里statistic越小越好,critical_values对应不同显著性水平,得自己比对,不是直接看 p
计算偏度峰度别只看 scipy.stats.skew 和 kurtosis 的原始值
默认 skew 和 kurtosis 返回的是 Fisher 定义(峰度减去 3),但很多人误以为“峰度=3 就是正态”——其实那是 excess kurtosis;真实正态分布的 Pearson 峰度是 3,Fisher 峰度才是 0。更麻烦的是,样本量小时这两个统计量方差极大,±0.5 的波动纯属噪声。
- 加参数
bias=False能减少小样本偏差,例如:stats.skew(x, bias=False) - 判断阈值别死守 ±0.5:n 200 后才考虑 ±0.5
- 别单独看数字:偏度为正但直方图右尾没异常值?可能是样本随机波动,配合 Q-Q 图看更准
Q-Q 图比所有数值检验都直观,但 statsmodels.api.qqplot 默认不标参考线
Q-Q 图一眼能看出哪里偏离、是否系统性(比如整体上翘说明右偏,S 形说明峰太尖或尾太厚)。但 qqplot 默认画完图不加 y=x 参考线,新手常误把散点趋势当结论。
- 必须加
line='45'参数:sm.qqplot(x, line='45'),否则图没参照系 - 如果数据量大(> 1000),点太多糊成一片,加
fit=True让它拟合正态分布后再画理论分位点,更清晰 - 注意坐标轴:横轴是理论分位数,纵轴是样本分位数;若纵轴明显弯曲,说明分布形状问题,不是均值或方差偏移
极值检测不能只靠 np.percentile 切 1% 和 99%
用分位数截断极值看似简单,但正态分布本身就有约 0.3% 数据落在 ±3σ 外——直接切 1%/99% 会误删合理极值,尤其当样本偏斜时,上下界不对称,单靠对称截断等于强行拉直尾巴。
立即学习“Python免费学习笔记(深入)”;
- 先看分布形态:若
skew > 0.5,用np.percentile(x, [1, 99])会低估上界,改用 IQR 法:q1, q3 = np.percentile(x, [25, 75]); iqr = q3 - q1; upper = q3 + 1.5 * iqr - 若要做稳健标准化(比如喂给模型),优先用
sklearn.preprocessing.RobustScaler,它内部就基于 IQR,不用自己算 - 警惕“极值=噪声”思维:金融收益率、响应时间等天然重尾,切掉可能丢掉关键信号
实际用时,最常被跳过的一步是:检验前先画直方图 + Q-Q 图。数值指标再漂亮,图上明显弯折也得回头查数据生成逻辑——比如是否混入了不同来源的子样本,或者存在未处理的离群实验条件。









