
spss默认对数据执行lilliefors修正的k-s检验(即估计均值和标准差后检验正态性),而scipy.stats.kstest默认检验是否服从**指定参数**的标准正态分布,二者原假设与参数设定不同,导致统计量和p值显著差异。
在进行正态性检验时,若直接用 scipy.stats.kstest(data, 'norm') 或 kstest(data, norm(loc=0,scale=1).cdf),实际检验的是“数据是否来自标准正态分布 N(0,1)”,这在绝大多数实际场景中既不合理也不适用——因为原始数据(如年龄、身高)显然不以0为均值、1为标准差。而SPSS的“探索(Explore)→ 正态性检验”模块默认采用的是 Lilliefors校正的Kolmogorov-Smirnov检验:它仍基于KS统计量,但将总体均值和标准差由样本估计得出,并通过模拟或查表调整p值,从而解决“参数未知却代入检验”所导致的I类错误膨胀问题。
例如,对示例中的 age 变量(共42个整数观测值),SPSS报告 KS 统计量为 0.190(p 检验目标根本不同。
✅ 正确做法:使用参数自估计 + Lilliefors校正的检验方法。SciPy 自 1.8.0 版本起提供了 scipy.stats.goodness_of_fit 接口支持此功能:
from scipy import stats
import numpy as np
# 加载 age 数据(注意:原题代码误将列名写为'weight',应为'height';此处取age列)
age = np.array([8,8,8,8,10,9,8,7,6,5,7,7,7,8,6,6,9,10,10,9,9,5,7,6,6,5,8,6,5,6,6,9,6,8,10,10,6,6,7,5,6,7,10])
# 方法1:使用 goodness_of_fit(推荐,自动处理Lilliefors逻辑)
res = stats.goodness_of_fit(stats.norm, age, statistic='ks', random_state=42)
print(f"Lilliefors KS statistic: {res.statistic:.4f}") # ≈ 0.190
print(f"p-value (Monte Carlo): {res.pvalue:.3f}") # ≈ 0.001–0.003,与SPSS一致⚠️ 注意事项:
立即学习“Python免费学习笔记(深入)”;
- goodness_of_fit 默认通过蒙特卡洛模拟计算p值(需指定 random_state 保证可重现),结果略有浮动,但统计量稳定;
- 若使用旧版SciPy(
- 对于小样本(n Shapiro-Wilk检验(scipy.stats.shapiro)通常更灵敏、更可靠,SPSS在样本量≤50时也优先报告该结果:
shapiro_stat, shapiro_p = stats.shapiro(age) print(f"Shapiro-Wilk: W={shapiro_stat:.4f}, p={shapiro_p:.3f}")
? 总结:
SPSS与Python结果不一致,本质是检验范式差异——SPSS做的是参数未知的正态性检验(Lilliefors),而默认kstest做的是参数已知的分布匹配检验。要获得可比结果,必须统一检验逻辑:使用goodness_of_fit(..., statistic='ks')或lilliefors(),并优先考虑Shapiro-Wilk检验作为正态性评估的首选方法。










