一、假设检验基本概念
假设检验(Hypothesis Testing)是统计推断的核心工具之一,它通过样本数据对总体参数或分布形式做出判断。其基本思想是:先对总体提出一个假设,然后利用样本数据去检验这个假设是否合理。
1.1 原假设与备择假设
每个假设检验问题都包含两个对立假设:
- 原假设(Null Hypothesis, H₀): 通常代表"无差异"或"无效应"的陈述,是需要被验证的基准。例如:两组均值相等、相关系数为零。
- 备择假设(Alternative Hypothesis, H₁): 与原假设相对立的陈述,代表研究者希望证明的结论。
假设检验的三种形式
以检验总体均值 μ 为例:
- 双侧检验: H₀: μ = μ₀ vs H₁: μ ≠ μ₀
- 左侧单侧检验: H₀: μ ≥ μ₀ vs H₁: μ < μ₀
- 右侧单侧检验: H₀: μ ≤ μ₀ vs H₁: μ > μ₀
1.2 显著性水平 α
显著性水平(Significance Level, α)是拒绝原假设时所能承受的最大风险概率,通常取值为 0.05(5%)或 0.01(1%)。其含义是:当原假设为真时,我们错误地拒绝它的概率不超过 α。
α 的选取原则:
- 在医学、药物研发等高风险领域,通常取 α = 0.01 甚至 0.001
- 在社会科学等探索性研究中,常取 α = 0.05
- 在大规模数据筛查场景下,可使用 α = 0.1 以提高灵敏度
1.3 检验统计量
检验统计量(Test Statistic)是根据样本数据计算出的数值,用于判断是否拒绝原假设。常见的检验统计量包括:
- z 统计量: 用于大样本或已知总体方差的情况
- t 统计量: 用于小样本且总体方差未知的情况
- F 统计量: 用于方差分析或方差齐性检验
- χ² 统计量: 用于分类数据的拟合优度检验
# Python 实现单样本 t 检验
import numpy as np
from scipy import stats
# 生成样本数据
np.random.seed(42)
sample = np.random.normal(loc=102, scale=5, size=30)
# 单样本 t 检验:检验均值是否等于 100
t_stat, p_value = stats.ttest_1samp(sample, popmean=100)
print(f"t 统计量: {t_stat:.4f}")
print(f"p 值: {p_value:.6f}")
# 判断是否拒绝原假设
alpha = 0.05
if p_value < alpha:
print("拒绝原假设:均值显著不等于 100")
else:
print("无法拒绝原假设:均值与 100 无显著差异")
二、两类错误与统计功效
2.1 Type I 错误(假阳性)
第一类错误(Type I Error): 原假设实际上为真,但被错误地拒绝了。这相当于"假阳性"—— 误报了一个不存在的效应。犯第一类错误的概率就是显著性水平 α。
典型案例:
一种新药实际并无疗效(H₀ 为真),但临床试验结果却显示有效(拒绝了 H₀),这就是 Type I 错误。这正是为什么医学研究要求 α = 0.05 甚至更小——宁可漏过真效应,也不误报假效应。
2.2 Type II 错误(假阴性)
第二类错误(Type II Error): 原假设实际上为假,但未能被拒绝。这相当于"假阴性"—— 遗漏了一个真实存在的效应。犯第二类错误的概率记为 β。
两类错误的关系:
- 在样本量固定时,α 和 β 呈反向关系:降低 α 会增大 β,反之亦然
- 唯一同时降低两类错误的方法:增加样本量
- 在实际应用中,Type I 错误通常被认为比 Type II 错误更严重
2.3 统计功效(Power)
统计功效(Statistical Power) 定义为当备择假设为真时,正确拒绝原假设的概率,即 Power = 1 - β。统计功效反映了检验发现真实效应的能力。
影响统计功效的因素
- 效应量(Effect Size): 真实效应越大,越容易被检测到,功效越高
- 样本量(Sample Size): n 越大,功效越高
- 显著性水平 α: α 越大,功效越高(但代价是 Type I 错误增加)
- 变异程度: 数据变异越小,功效越高
# 使用 statsmodels 进行功效分析
from statsmodels.stats.power import TTestIndPower
# 指定参数计算所需样本量
effect_size = 0.5 # Cohen's d = 0.5(中等效应)
alpha = 0.05 # 显著性水平
power = 0.80 # 目标功效
analysis = TTestIndPower()
n = analysis.solve_power(
effect_size=effect_size,
alpha=alpha,
power=power,
alternative='two-sided'
)
print(f"所需样本量: {np.ceil(n):.0f}")
# 绘制功效曲线
import matplotlib.pyplot as plt
fig = analysis.plot_power(
dep_var='nobs',
nobs=np.arange(10, 500),
effect_size=[0.2, 0.5, 0.8],
alpha=0.05
)
plt.title('统计功效与样本量关系曲线')
| 效应量 (Cohen's d) |
小样本 (n=30) |
中样本 (n=100) |
大样本 (n=500) |
| 小 (0.2) |
0.14 |
0.29 |
0.80 |
| 中 (0.5) |
0.48 |
0.88 |
0.99 |
| 大 (0.8) |
0.81 |
0.99 |
1.00 |
|
注:表中数值为独立样本 t 检验在 α=0.05 双侧检验下的统计功效
|
Power Analysis 的应用场景:
- 实验设计阶段: 在研究开始前计算所需的最小样本量
- 研究预算规划: 权衡成本与统计功效,确定可行样本量
- 已发表研究评估: 评估已有研究的检验能力,判断阴性结果是否可信
三、p 值深度解读
3.1 p < 0.05 的真正含义
p 值是在原假设为真的前提下,观察到当前结果(或更极端结果)的概率。p < 0.05 意味着:如果原假设为真,那么出现当前观测数据的概率不到 5%。
常见的 p 值误读(请务必避免):
- 错误: p = 0.03 意味着原假设为假的概率是 97%
正确: p = 0.03 意味着在原假设为真的条件下,观测到当前结果的概率为 3%
- 错误: p = 0.03 意味着结果有 97% 的概率可重复
正确: p 值不衡量结果的可重复性
- 错误: p = 0.06 意味着两个组"没有差异"
正确: p = 0.06 意味着在 α = 0.05 水平上无法拒绝原假设,但不等于两组相同
3.2 p 值不是效应概率
这是最常见的误解之一。p 值衡量的是 数据相对于原假设的极端程度,而不是效应为真的概率。要计算效应为真的后验概率,需要使用贝叶斯方法。p 值也无法告诉我们效应量的大小——一个非常大的样本中,即使微不足道的差异也可能产生极小的 p 值。
"p 值是数据与原假设不一致程度的度量,而不是效应存在的概率。一个很小的 p 值可能来自一个很大的样本量和一个很小的效应,而非一个很大的效应。" —— 美国统计学会(ASA)关于 p 值的声明,2016
3.3 p-hacking 与多重比较问题
p-hacking(p 值操纵) 指研究者通过多种数据分析和选择性报告的方式,人为获得显著 p 值的行为。常见形式包括:
- 反复分析数据,每次排除不同的"异常值"直到结果显著
- 同时测试多个结局指标,只报告显著的结果
- 在获得足够大的样本量之前反复做中期分析,一旦显著就停止收集数据
- 将连续变量随意分组,尝试不同切分点直到显著
多重比较校正方法
当同时进行多个假设检验时,需要校正显著性水平以控制整体 Type I 错误率:
- Bonferroni 校正: 将 α 除以比较次数 m,即 α' = α / m。最保守,控制 Family-wise Error Rate (FWER)
- Benjamini-Hochberg 校正(FDR): 控制错误发现率(False Discovery Rate),比 Bonferroni 更宽松,在探索性分析中更常用
- Holm-Bonferroni 校正: 逐步降序法,比标准 Bonferroni 略温和
# p 值校正示例
from scipy.stats import false_discovery_control
import numpy as np
# 假设进行了 10 次检验,得到如下 p 值
p_values = np.array([0.001, 0.02, 0.03, 0.05, 0.10,
0.15, 0.25, 0.40, 0.60, 0.80])
# Bonferroni 校正
m = len(p_values)
bonferroni_cutoff = 0.05 / m
print(f"Bonferroni 校正阈值: {bonferroni_cutoff:.6f}")
print(f"Bonferroni 显著: {p_values < bonferroni_cutoff}")
# FDR 校正 (Benjamini-Hochberg)
reject, p_corrected, _, _ = false_discovery_control(p_values)
print(f"FDR 校正后显著的 p 值: {p_values[reject]}")
四、正态性检验
许多统计检验(如 t 检验、ANOVA)假设数据服从正态分布。正态性检验用于评估这一假设是否成立。以下介绍四种常用的正态性检验方法。
4.1 Shapiro-Wilk 检验
Shapiro-Wilk 检验是最常用的正态性检验之一,尤其适用于 小样本(n < 5000) 的情况。它基于顺序统计量的比值计算检验统计量 W,W 越接近 1 说明数据越接近正态分布。
# Shapiro-Wilk 正态性检验
from scipy.stats import shapiro
# 生成正态分布数据
np.random.seed(42)
normal_data = np.random.normal(loc=0, scale=1, size=100)
stat_w, p_shapiro = shapiro(normal_data)
print(f"Shapiro-Wilk W 统计量: {stat_w:.4f}")
print(f"p 值: {p_shapiro:.4f}")
print("结论: 数据服从正态分布" if p_shapiro > 0.05
else "结论: 数据不服从正态分布")
4.2 D'Agostino K² 检验
D'Agostino K² 检验基于数据的 偏度(Skewness) 和 峰度(Kurtosis) 联合检验正态性。它计算一个综合的 K² 统计量,在大样本下近似服从 χ² 分布。
# D'Agostino K² 检验
from scipy.stats import normaltest
stat_k2, p_k2 = normaltest(normal_data)
print(f"D'Agostino K² 统计量: {stat_k2:.4f}")
print(f"p 值: {p_k2:.4f}")
# 检查偏度和峰度
from scipy.stats import skew, kurtosis
print(f"偏度: {skew(normal_data):.4f}")
print(f"峰度: {kurtosis(normal_data):.4f}")
4.3 Anderson-Darling 检验
Anderson-Darling 检验是 EDF(经验分布函数)检验的一种,对分布的尾部差异特别敏感。它不仅可以检验正态性,还可以检验其他分布(如指数分布、极值分布等)。
# Anderson-Darling 检验
from scipy.stats import anderson
result = anderson(normal_data, dist='norm')
print(f"AD 统计量: {result.statistic:.4f}")
print("临界值:")
for cv, sl in zip(result.critical_values, result.significance_level):
print(f" 显著性水平 {sl}%: {cv:.4f}")
print(f"结论: {'数据服从正态分布' if result.statistic < result.critical_values[2] else '数据不服从正态分布'}")
4.4 Q-Q 图(可视化方法)
Q-Q 图(Quantile-Quantile Plot)通过比较数据的分位数与理论正态分布的分位数来直观判断正态性。如果数据点大致落在参考线上,则数据接近正态分布。
# Q-Q 图绘制
import matplotlib.pyplot as plt
import scipy.stats as stats
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# 正态数据
stats.probplot(normal_data, dist="norm", plot=axes[0])
axes[0].set_title("正态数据的 Q-Q 图")
# 偏态数据对比
skewed_data = np.random.exponential(scale=2, size=100)
stats.probplot(skewed_data, dist="norm", plot=axes[1])
axes[1].set_title("偏态数据的 Q-Q 图")
plt.tight_layout()
plt.show()
| 方法 |
适用场景 |
优点 |
缺点 |
| Shapiro-Wilk |
n < 5000 |
检验效力高,公认的黄金标准 |
大样本时计算量大,过于敏感 |
| D'Agostino K² |
n ≥ 20 |
可解析偏度和峰度的具体偏差 |
对尾部偏差不敏感 |
| Anderson-Darling |
n ≥ 5 |
对尾部差异敏感,支持多种分布 |
临界值需查表,需要指定分布 |
| Q-Q 图 |
任意样本量 |
直观可视,可发现异常模式 |
主观判断,不如数值检验精确 |
正态性检验注意事项:
- 大样本陷阱: 当 n 很大时(如 > 5000),即使数据非常接近正态分布,正态性检验也可能拒绝 H₀。此时应结合 Q-Q 图综合判断。
- 小样本局限: 当 n 很小时(如 < 10),正态性检验的效力不足,难以检测出偏离。此时应依赖领域知识判断。
- 中心极限定理: 对于 t 检验等均值比较方法,当样本量足够大(n ≥ 30)时,即使数据轻微偏离正态分布,结果仍然稳健。
五、方差齐性检验
方差齐性(Homogeneity of Variance)是指多个组的总体方差相等。许多统计方法(如独立样本 t 检验、ANOVA)要求各组方差齐性。
5.1 Levene 检验
Levene 检验对数据分布的正态性假设不敏感,是最稳健的方差齐性检验方法。它使用各组数据与其组中位数的绝对离差进行 ANOVA。
# Levene 方差齐性检验
from scipy.stats import levene
# 生成三组数据
group1 = np.random.normal(loc=0, scale=1, size=50)
group2 = np.random.normal(loc=2, scale=1, size=50)
group3 = np.random.normal(loc=1, scale=2, size=50) # 方差不同
stat_l, p_l = levene(group1, group2, group3)
print(f"Levene 统计量: {stat_l:.4f}")
print(f"p 值: {p_l:.4f}")
print("结论: 各组方差齐性" if p_l > 0.05
else "结论: 各组方差不齐")
5.2 Bartlett 检验
Bartlett 检验基于各组方差的加权算术平均和几何平均之比构造检验统计量。它 对正态性假设非常敏感——如果数据偏离正态分布,Bartlett 检验的结果可能不可靠。
# Bartlett 检验(要求数据正态)
from scipy.stats import bartlett
stat_b, p_b = bartlett(group1, group2, group3)
print(f"Bartlett 统计量: {stat_b:.4f}")
print(f"p 值: {p_b:.4f}")
5.3 Fligner-Killeen 检验
Fligner-Killeen 检验是一种非参数的方差齐性检验方法,基于各组数据相对于中位数的绝对偏离进行秩变换。它不要求数据正态分布,且对异常值比较稳健。
# Fligner-Killeen 检验(非参数方法)
from scipy.stats import fligner
stat_fk, p_fk = fligner(group1, group2, group3)
print(f"Fligner-Killeen 统计量: {stat_fk:.4f}")
print(f"p 值: {p_fk:.4f}")
| 检验方法 |
是否需要正态性 |
稳健性 |
适用场景 |
| Levene 检验 |
不需要 |
高(最稳健) |
通用首选,特别是数据非正态时 |
| Bartlett 检验 |
需要 |
低(对偏离敏感) |
仅当数据确认正态分布时 |
| Fligner-Killeen 检验 |
不需要 |
中等 |
数据非正态且有异常值时 |
六、置信区间
置信区间(Confidence Interval)给出了参数估计的一个区间范围,反映了估计的不确定性。95% 置信区间的含义是:如果重复抽样 100 次并计算 100 个置信区间,大约有 95 个区间包含真实的总体参数。
6.1 均值的置信区间
当总体方差未知时,均值的置信区间基于 t 分布计算:
# 手动计算均值置信区间
from scipy.stats import t
data = np.random.normal(loc=100, scale=15, size=50)
n = len(data)
mean = np.mean(data)
se = stats.sem(data) # 标准误
alpha = 0.05
t_crit = t.ppf(1 - alpha/2, df=n-1)
ci_lower = mean - t_crit * se
ci_upper = mean + t_crit * se
print(f"样本均值: {mean:.2f}")
print(f"95% 置信区间: ({ci_lower:.2f}, {ci_upper:.2f})")
# 使用 scipy 直接计算
ci = stats.t.interval(0.95, df=n-1, loc=mean, scale=se)
print(f"验证: ({ci[0]:.2f}, {ci[1]:.2f})")
6.2 Bootstrap 自助法
Bootstrap 是一种基于重采样(resampling)的非参数统计方法,适用于难以用公式推导置信区间的情况。它通过对原始数据进行有放回抽样,模拟抽样分布,计算经验置信区间。
Bootstrap 置信区间计算步骤
- 从原始样本中 有放回 抽取 n 个观测值,形成 Bootstrap 样本
- 计算该 Bootstrap 样本的目标统计量(如均值、中位数)
- 重复步骤 1-2 共 B 次(通常 B ≥ 1000),得到 B 个 Bootstrap 统计量
- 取 Bootstrap 分布的 α/2 和 1-α/2 分位数作为置信区间上下限
# Bootstrap 置信区间(以中位数为例)
np.random.seed(42)
data = np.random.exponential(scale=3, size=100) # 偏态数据
B = 10000
bootstrap_stats = np.zeros(B)
for i in range(B):
boot_sample = np.random.choice(data, size=len(data), replace=True)
bootstrap_stats[i] = np.median(boot_sample)
ci_lower = np.percentile(bootstrap_stats, 2.5)
ci_upper = np.percentile(bootstrap_stats, 97.5)
print(f"样本中位数: {np.median(data):.2f}")
print(f"Bootstrap 95% 置信区间: ({ci_lower:.2f}, {ci_upper:.2f})")
# 使用 scipy 内置 bootstrap 函数
from scipy.stats import bootstrap
res = bootstrap((data,), np.median, n_resamples=9999,
confidence_level=0.95)
print(f"scipy 结果: ({res.confidence_interval.low:.2f}, {res.confidence_interval.high:.2f})")
Bootstrap 的优缺点:
- 优点: 无需假设数据分布形态、适用于复杂统计量(中位数、相关系数等)、实现简单
- 缺点: 计算量大(需重复抽样数千次)、对原始样本的代表性有依赖、极端小样本效果不佳
七、效应量
p 值告诉我们差异是否"统计显著",但无法告诉我们差异是否"实际重要"。效应量(Effect Size)衡量的是效应的大小,帮助我们判断结果的实际意义。
7.1 Cohen's d
Cohen's d 是最常用的效应量指标之一,衡量两组均值之间的标准化差异。它不受样本量的影响,使得不同研究之间的效应可以相互比较。
# 手动计算 Cohen's d
def cohens_d(group1, group2):
n1, n2 = len(group1), len(group2)
s1, s2 = np.var(group1, ddof=1), np.var(group2, ddof=1)
# 合并标准差
s_pooled = np.sqrt(((n1-1)*s1 + (n2-1)*s2) / (n1 + n2 - 2))
# Cohen's d
d = (np.mean(group1) - np.mean(group2)) / s_pooled
return d
group_a = np.random.normal(loc=100, scale=15, size=50)
group_b = np.random.normal(loc=108, scale=15, size=50)
d = cohens_d(group_a, group_b)
print(f"Cohen's d = {d:.3f}")
# 解释效应量(Cohen 标准)
if abs(d) < 0.2:
print("效应量: 极小 (trivial)")
elif abs(d) < 0.5:
print("效应量: 小 (small)")
elif abs(d) < 0.8:
print("效应量: 中 (medium)")
else:
print("效应量: 大 (large)")
7.2 Eta-squared (η²)
Eta-squared 用于 ANOVA(方差分析),衡量自变量对因变量变异的解释比例。η² 的取值范围为 [0, 1],值越大表示自变量的效应越强。
# 计算 Eta-squared
from scipy.stats import f_oneway
k1 = np.random.normal(loc=50, scale=10, size=30)
k2 = np.random.normal(loc=55, scale=10, size=30)
k3 = np.random.normal(loc=60, scale=10, size=30)
# ANOVA
f_stat, p_anova = f_oneway(k1, k2, k3)
# 计算 eta-squared
all_data = np.concatenate([k1, k2, k3])
grand_mean = np.mean(all_data)
group_means = [np.mean(g) for g in (k1, k2, k3)]
group_sizes = [len(g) for g in (k1, k2, k3)]
ss_between = sum(n * (m - grand_mean)**2
for n, m in zip(group_sizes, group_means))
ss_total = sum((x - grand_mean)**2 for x in all_data)
eta_sq = ss_between / ss_total
print(f"η² = {eta_sq:.4f}")
print(f"F 统计量: {f_stat:.3f}, p 值: {p_anova:.5f}")
7.3 实际显著性 vs 统计显著性
这是数据分析中最容易被忽视的区别之一:
重要区分:
统计显著性(Statistical Significance): p < 0.05,表示观察到的效应不太可能由随机误差引起。但这仅说明效应存在,并不说明效应有多大或多重要。
实际显著性(Practical Significance): 效应量大到足以在实际应用中产生有意义的影响。一个统计显著的微小差异可能在实际中毫无价值。
典型案例:
假设某减肥药临床试验中,实验组比对照组平均多减重 0.3 公斤。在 10000 人的大样本下,这一差异完全可能达到统计显著(p < 0.001),但 0.3 公斤的减重效果在实际临床中几乎没有意义——这并不是一个有实际价值的减肥效果。
因此,报告结果时应当始终同时汇报 p 值和效应量,让读者能全面评估结果的意义。
| 指标 |
回答的问题 |
受样本量影响 |
| p 值 |
效应是否存在(是否显著) |
是(大样本更容易显著) |
| 效应量 |
效应有多大(是否重要) |
否(理论上不依赖样本量) |
| 置信区间 |
效应的估计范围有多精确 |
是(大样本区间更窄) |
八、scipy.stats 检验函数总结
scipy.stats 提供了丰富的假设检验函数,以下是对常用函数的系统总结:
8.1 均值比较检验
| 函数 |
用途 |
前提假设 |
语法要点 |
ttest_1samp |
单样本 t 检验(均值 vs 常数) |
数据正态分布 |
ttest_1samp(a, popmean) |
ttest_ind |
独立样本 t 检验(两组均值比较) |
正态分布、方差齐性 |
ttest_ind(a, b, equal_var=True) |
ttest_rel |
配对样本 t 检验(前后比较) |
差值正态分布 |
ttest_rel(a, b) |
mannwhitneyu |
Mann-Whitney U 检验(非参数独立样本) |
无分布假设 |
mannwhitneyu(x, y, alternative='two-sided') |
wilcoxon |
Wilcoxon 符号秩检验(非参数配对样本) |
差值对称分布 |
wilcoxon(x, y) |
8.2 方差分析
| 函数 |
用途 |
前提假设 |
语法要点 |
f_oneway |
单因素方差分析(三组及以上均值比较) |
正态分布、方差齐性 |
f_oneway(*groups) |
kruskal |
Kruskal-Wallis H 检验(非参数 ANOVA) |
无分布假设 |
kruskal(*groups) |
8.3 相关性检验
| 函数 |
用途 |
前提假设 |
语法要点 |
pearsonr |
Pearson 相关系数(线性相关) |
双变量正态分布 |
pearsonr(x, y) 返回 (r, p) |
spearmanr |
Spearman 秩相关系数(单调相关) |
无分布假设 |
spearmanr(a, b) |
kendalltau |
Kendall Tau 相关系数(有序数据) |
无分布假设 |
kendalltau(x, y) |
chi2_contingency |
卡方检验(分类变量独立性) |
期望频数 ≥ 5 |
chi2_contingency(observed) |
8.4 正态性与分布检验
| 函数 |
用途 |
语法要点 |
shapiro |
Shapiro-Wilk 正态性检验 |
shapiro(x) 返回 (W, p) |
normaltest |
D'Agostino K² 正态性检验 |
normaltest(x) 返回 (K², p) |
anderson |
Anderson-Darling 正态性检验 |
anderson(x, dist='norm') 返回 (stat, critical_values) |
ks_1samp |
Kolmogorov-Smirnov 单样本检验 |
ks_1samp(x, cdf) |
8.5 方差齐性检验
| 函数 |
用途 |
语法要点 |
levene |
Levene 方差齐性检验(推荐首选) |
levene(*samples) 返回 (stat, p) |
bartlett |
Bartlett 方差齐性检验(需正态) |
bartlett(*samples) 返回 (stat, p) |
fligner |
Fligner-Killeen 方差齐性检验(非参数) |
fligner(*samples) 返回 (stat, p) |
检验选择决策指南:
- 步骤一: 用 Shapiro-Wilk 检验数据是否正态 → 是则用参数检验,否则用非参数检验
- 步骤二(参数检验): 用 Levene 检验方差是否齐性 ← 是则用标准方法,否则用 Welch's t 检验(
ttest_ind(equal_var=False))
- 步骤三: 选择正确的效应量指标报告,同时评估统计显著性和实际显著性
# scipy.stats 假设检验完整流程示例
from scipy import stats
import numpy as np
np.random.seed(42)
control = np.random.normal(loc=100, scale=15, size=40)
treatment = np.random.normal(loc=110, scale=15, size=40)
# 1. 正态性检验
_, p1 = stats.shapiro(control)
_, p2 = stats.shapiro(treatment)
print(f"正态性检验: control p={p1:.4f}, treatment p={p2:.4f}")
# 2. 方差齐性检验
_, p_var = stats.levene(control, treatment)
print(f"方差齐性 Levene 检验: p={p_var:.4f}")
# 3. 选择适当的 t 检验
equal_var = p_var > 0.05
t_stat, p_value = stats.ttest_ind(control, treatment,
equal_var=equal_var)
print(f"独立样本 t 检验: t={t_stat:.3f}, p={p_value:.5f}")
# 4. 效应量
n1, n2 = len(control), len(treatment)
s1, s2 = np.var(control, ddof=1), np.var(treatment, ddof=1)
s_p = np.sqrt(((n1-1)*s1 + (n2-1)*s2) / (n1 + n2 - 2))
d = (np.mean(treatment) - np.mean(control)) / s_p
print(f"效应量 Cohen's d = {d:.3f}")
# 5. 置信区间
se = s_p * np.sqrt(1/n1 + 1/n2)
t_crit = stats.t.ppf(0.975, df=n1+n2-2)
diff = np.mean(treatment) - np.mean(control)
print(f"均值差 95% CI: ({diff - t_crit*se:.2f}, {diff + t_crit*se:.2f})")
九、常见误区与最佳实践
9.1 统计显著 ≠ 实际重要
如前所述,大样本可以使微小差异达到统计显著。始终报告效应量和置信区间,帮助读者理解结果的实际意义。
9.2 不显著 ≠ 无效应
p > 0.05 不代表原假设为真,只说明没有足够的证据拒绝原假设。可能的原因包括:样本量不足、效应量太小、数据变异太大或测量误差较大。
9.3 避免"p 值崇拜"
不要以 p < 0.05 作为判断结果价值的唯一标准。美国统计协会(ASA)2016 年的声明明确警告 p 值的误用和滥用,强调应该结合效应量、置信区间和研究设计综合判断。
假设检验最佳实践清单
- 在研究设计阶段进行 Power Analysis 确定样本量
- 预先确定显著性水平 α,不要在收集数据后再选
- 同时报告 p 值、效应量和置信区间
- 使用 Q-Q 图和正态性检验 验证前提假设
- 必要时进行 多重比较校正
- 考虑 Bootstrap 等非参数方法 作为补充分析
- 在探索性研究和验证性研究之间 明确区分
- 公开分析代码和数据,确保结果 可复现
十、核心要点总结
- 假设检验基本框架: 提出原假设 H₀ 和备择假设 H₁,选择显著性水平 α,计算检验统计量和 p 值,做出统计推断
- 两类错误: Type I(假阳性,概率为 α)和 Type II(假阴性,概率为 β),统计功效 Power = 1 - β
- p 值正确理解: 在原假设为真的条件下观察到当前结果的概率,不是效应为真的概率
- 前提假设验证: 正态性检验(Shapiro-Wilk 适合小样本、AD 检验对尾部敏感)和方差齐性检验(Levene 最稳健)是参数检验的前提
- 置信区间: 反映估计的不确定性,Bootstrap 自助法适用于复杂统计量或非正态数据
- 效应量: Cohen's d(两组比较)、η²(ANOVA),告诉读者效应有多大而非仅仅是否存在
- 检验工具: scipy.stats 提供了完整的参数和非参数检验函数家族,根据数据特征正确选择
- 报告规范: 完整的统计分析报告应当同时包含 p 值、效应量和置信区间三要素