在统计分析和机器学习建模前,确认数值特征是否符合正态分布是很多流程的必要环节,Shapiro-Wilk检验是检验小样本数据正态性的常用方法,当需要对数据框中多个数值列同时开展检验时,手动逐个操作会消耗大量时间,通过编写通用函数可以实现高效批量处理。

Shapiro-Wilk检验的基本原理
Shapiro-Wilk检验的原假设是样本数据来自正态分布总体,检验结果会返回两个值:统计量W和对应的p值。通常我们设定显著性水平为0.05,当p值大于0.05时,无法拒绝原假设,认为该列数据符合正态分布;当p值小于等于0.05时,拒绝原假设,认为该列数据不符合正态分布。
批量检验的实现思路
批量处理的核心逻辑是遍历数据框的所有列,先筛选出数值类型的列,再对每个数值列单独调用Shapiro-Wilk检验的方法,最后将每列的检验结果整理成统一的结构返回。具体步骤如下:
- 导入需要的依赖库,包括pandas用于数据处理,scipy.stats中的shapiro函数用于执行检验
- 定义批量检验函数,接收数据框作为参数
- 遍历数据框的列,判断列的数据类型是否为数值型
- 对数值列执行shapiro检验,记录列名、检验统计量和p值
- 将所有结果整理成数据框返回
完整代码实现
以下是完整的批量检验代码,包含模拟数据生成和检验逻辑:
import pandas as pd
import numpy as np
from scipy.stats import shapiro
# 生成模拟数据,包含3个数值列和1个非数值列
np.random.seed(42)
data = pd.DataFrame({
"col1": np.random.normal(loc=0, scale=1, size=100), # 符合正态分布的列
"col2": np.random.exponential(scale=1, size=100), # 不符合正态分布的列
"col3": np.random.normal(loc=5, scale=2, size=100), # 符合正态分布的列
"col4": ["a", "b", "c"] * 33 + ["a"] # 非数值列,不参与检验
})
def batch_shapiro_test(df, alpha=0.05):
"""
批量对数据框中的数值列执行Shapiro-Wilk正态性检验
参数:
df: pandas数据框
alpha: 显著性水平,默认0.05
返回:
包含每列检验结果的DataFrame
"""
result_list = []
# 遍历所有列
for col in df.columns:
# 判断是否为数值类型列
if pd.api.types.is_numeric_dtype(df[col]):
# 执行Shapiro-Wilk检验,去除缺失值
valid_data = df[col].dropna()
if len(valid_data) < 3:
# Shapiro-Wilk检验要求样本量至少为3
result_list.append({
"列名": col,
"检验统计量W": np.nan,
"p值": np.nan,
"是否符合正态分布": "样本量不足,无法检验"
})
continue
stat, p_value = shapiro(valid_data)
# 根据p值判断结果
is_normal = "是" if p_value > alpha else "否"
result_list.append({
"列名": col,
"检验统计量W": round(stat, 4),
"p值": round(p_value, 4),
"是否符合正态分布": is_normal
})
return pd.DataFrame(result_list)
# 执行批量检验
test_result = batch_shapiro_test(data)
print(test_result)
代码结果说明
运行上述代码后,输出的结果表格会清晰展示每个数值列的检验情况,比如col1和col3的p值会大于0.05,标记为符合正态分布,col2的p值会小于0.05,标记为不符合正态分布,col4作为非数值列不会出现在结果中。如果某列数值的有效样本量小于3,函数会返回样本量不足的提示,避免检验出错。
注意事项
Shapiro-Wilk检验对样本量有一定要求,通常适合样本量在3到5000之间的数据,当样本量过大时,即使数据轻微偏离正态分布,检验也可能返回很小的p值,此时可以结合直方图、Q-Q图等方式辅助判断。另外如果数据中存在大量缺失值,需要提前处理,避免影响检验结果的准确性。
Shapiro-Wilk_test正态性检验批量处理数值列Python修改时间:2026-06-13 02:24:25