
spss 与 python 的 kolmogorov-smirnov(ks)检验结果常出现显著差异,主因在于二者默认检验假设不同:spss 默认执行参数未知的 lilliefors 校正版 ks 检验,而 scipy 的 `kstest` 默认检验是否服从**指定参数**(如标准正态)分布,直接套用会导致统计量失真、p 值极小且无实际意义。
在正态性检验实践中,一个常见误区是:将原始数据(如 age)或其对数变换后,直接使用 scipy.stats.kstest(data, 'norm') 或 kstest(data, norm(loc=0, scale=1).cdf) 进行检验。这种写法隐含了“数据应服从均值为 0、标准差为 1 的标准正态分布”这一强假设——而现实中,样本通常来自位置和尺度未知的正态总体。因此,当您运行:
from scipy import stats import numpy as np # 示例: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]) result = stats.kstest(age, 'norm') # 等价于 norm(loc=0, scale=1) print(result) # statistic ≈ 0.99999, p ≈ 0 → 虚假拒绝!
得到的 KS 统计量接近 1、p 值趋近于 0,并非因为数据严重偏离正态,而是因为 age 的均值约 7.5、标准差约 1.7,与标准正态(μ=0, σ=1)完全不匹配。该检验本质上在问:“这些数据是否来自 N(0,1)?”答案显然是否定的——但这与“是否服从某个正态分布”毫无关系。
✅ 正确做法:使用 Lilliefors 检验(KS 的参数估计校正版)
SPSS 中的“单样本 KS 检验”在勾选“正态性”时,实际调用的是 Lilliefors 检验:它先用样本估计 μ 和 σ,再基于此拟合正态分布计算 KS 统计量,并采用专门的校正临界值(非标准 KS 分布),从而解决参数估计带来的偏差问题。
SciPy 原生不提供 Lilliefors 检验,但可通过 statsmodels 实现:
from statsmodels.stats.diagnostic import lilliefors
# 对 age 进行 Lilliefors 检验(自动估计 mu/sigma)
stat_age, p_age = lilliefors(age, dist='norm', pvalmethod='table')
print(f"age: statistic={stat_age:.3f}, p-value={p_age:.3f}") # 输出接近 SPSS 的 0.190 / 0.000
# 对 height(需从原始数据提取)同理
height = np.array([120,123,130,125,160,158,120,126,98,97,115,120,118,117,97,99,123,157,155,155,
153,96,115,94,94,87,117,96,97,91,88,149,94,117,156,160,90,90,116,89,90,118,162])
stat_ht, p_ht = lilliefors(height, dist='norm', pvalmethod='table')
print(f"height: statistic={stat_ht:.3f}, p-value={p_ht:.3f}") # 接近 SPSS 的 0.173 / 0.002⚠️ 注意事项:
立即学习“Python免费学习笔记(深入)”;
- lilliefors 的 pvalmethod='table' 使用查表法(推荐,精度高);若需更高精度或大样本,可设 pvalmethod='approx'(近似公式)。
- 不要对数据做任意变换(如 np.log(age))后再用标准 KS 检验——除非你明确想检验“log(age) 是否服从标准正态”,而非原变量正态性。
- 对于小样本(n Shapiro-Wilk 检验(scipy.stats.shapiro)统计功效更高,且无需指定分布参数,是正态性检验的首选:
from scipy.stats import shapiro
w_stat, w_p = shapiro(age)
print(f"Shapiro-Wilk for age: W={w_stat:.3f}, p={w_p:.3f}") # 更稳健的结论? 总结:SPSS 与 Python KS 结果不一致,根源在于检验假设错配。务必根据分析目标选择恰当方法——验证“是否服从某正态分布”请用 Lilliefors 或 Shapiro-Wilk;验证“是否服从特定已知分布(如 N(0,1))”才用 scipy.stats.kstest。忽略此区别将导致严重统计误判。










