Python中Anderson-Darling测试出现除零错误的解决方法
问题:Anderson-Darling正态性检验处理含大量零值和小值数据时的报错与异常结果
问题说明
尝试用Anderson-Darling检验验证一组数据的正态性,但数据包含大量零值和众多小非零值,运行时触发以下警告:
RuntimeWarning: divide by zero encountered in log
S = sum((2 * i-1.0)/ N * (log(z)+log(1-z[::-1])),axis=0)
同时测试统计量显示为inf;示例代码运行后得到20+的不合理统计量,实际数据含约1000个零值,问题更严重。
示例代码
import numpy as np from scipy import stats data = np.array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00, 9.90000010e-01, 0.00000000e+00, 9.90000010e-01, 1.00000000e+00, 9.30000007e-01, 1.00000000e+00, 1.00000000e+00, 2.00000000e+00, 1.99000001e+00, 9.30000007e-01, 9.90000010e-01, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00, 1.93000001e+00, 1.00000000e+00, 1.99000001e+00, 2.94000000e+00, 1.00000000e+00, 5.83000004e+00, 5.83000004e+00, 6.91000003e+00, 6.82999998e+00, 1.07800000e+01, 9.77000004e+00, 1.34700000e+01, 1.77100000e+01, 2.76000001e+01, 5.09000002e+01, 9.92300003e+01, 1.99720001e+02, 3.94330001e+02, 8.10660002e+02, 1.60540001e+03, 2.83691001e+03, 4.46896001e+03, 5.48025002e+03, 5.21601002e+03, 3.94428001e+03, 2.48591001e+03, 1.56996000e+03, 9.49610003e+02, 5.92650002e+02, 4.02490001e+02, 2.93620001e+02, 2.16200001e+02, 1.43060001e+02, 1.22550000e+02, 9.20400003e+01, 9.50000004e+01, 6.97500002e+01, 6.26600003e+01, 5.37800002e+01, 5.31300001e+01, 5.01200002e+01, 4.25000002e+01, 3.14000001e+01, 2.94300001e+01, 3.41700001e+01, 3.16100001e+01, 2.83400001e+01, 1.86500001e+01, 1.76200001e+01, 2.06500001e+01, 1.38100001e+01, 1.37600001e+01, 1.26400000e+01, 1.17600001e+01, 5.85000002e+00, 1.29200000e+01, 1.09100000e+01, 5.97000003e+00, 3.99000001e+00, 4.92000002e+00, 8.84000003e+00, 5.80000001e+00, 3.91000003e+00, 5.96000004e+00, 2.88000000e+00]]) print(stats.anderson(data))
解决建议
- 报错根源:Anderson-Darling检验需计算数据累积分布函数(CDF)的对数,当数据存在大量重复零值或极小值时,CDF会趋近于0或1,导致
log(0)或log(1-1)的无效计算,触发警告并使统计量变为inf。 - 数据预处理方案:
- 若零值代表“检测下限以下”的截断数据,直接改用截尾正态分布的拟合与检验,而非标准正态检验;
- 对非零小值添加极小偏移量(如
data[data>0] += 1e-8),避免CDF值极端接近0,但需在分析报告中说明该操作对数据的影响; - 先做可视化判断:从示例数据的数值分布看,数据明显右偏(多数小值、少数极大值),本身不符合正态分布特征,建议绘制直方图、QQ图直观确认分布形态。
- 替代检验方法:
- 使用对重复值、极端值更鲁棒的检验,比如Shapiro-Wilk检验(注意样本量过大时该检验的局限性);
- 针对右偏数据尝试对数变换(如
np.log(data[data>0]+1)),变换后再做正态性检验,若符合正态分布,可推断原数据服从对数正态分布。
- 多维数据处理注意:示例代码中的
data是二维数组,stats.anderson会对每列单独检验;若你的数据是一维的,需先展平数组(data.flatten())后再传入函数。
内容的提问来源于stack exchange,提问作者VerityR
相关产品推荐
相关产品推荐

