用Python实战贾俊平《统计学》第八章:手把手教你用SciPy搞定假设检验课后习题
统计学作为数据科学的基石,假设检验是其中最具实用价值的方法论之一。传统教材往往侧重理论推导和手工计算,但在大数据时代,掌握如何用编程工具自动化完成这些分析已成为必备技能。本文将带您用Python的SciPy和Statsmodels库,重新解构贾俊平《统计学》第八章的经典习题,从代码实现角度深入理解假设检验的精髓。
1. 环境配置与工具准备
工欲善其事,必先利其器。在开始之前,我们需要配置好Python数据分析的黄金组合:
# 安装必要库(如未安装) !pip install numpy scipy statsmodels matplotlib pandas现代Python科学计算生态已经为我们提供了强大的统计工具集:
- SciPy:提供各种统计检验函数(ttest、ztest、chisquare等)
- Statsmodels:更专业的统计建模工具,包含更多检验变体
- Pandas:数据整理与分析利器
- Matplotlib:可视化检验结果
提示:推荐使用Jupyter Notebook进行交互式操作,可以实时查看检验结果和可视化输出。
2. 单样本检验实战
2.1 Z检验:铁水含碳量分析
教材第一题是典型的单样本Z检验案例:已知总体标准差,检验样本均值是否等于特定值。让我们用Python实现:
import numpy as np from scipy import stats # 题目参数 mu0 = 4.55 # 总体均值 sigma = 0.108 # 总体标准差 x_bar = 4.484 # 样本均值 n = 9 # 样本量 alpha = 0.05 # 显著性水平 # 计算Z统计量和p值 z_score = (x_bar - mu0)/(sigma/np.sqrt(n)) p_value = 2 * (1 - stats.norm.cdf(abs(z_score))) # 双侧检验 print(f"Z统计量: {z_score:.3f}") print(f"P值: {p_value:.4f}") # 与临界值比较 z_critical = stats.norm.ppf(1-alpha/2) print(f"临界Z值: ±{z_critical:.3f}")输出结果将显示:
- Z统计量:-1.833
- P值:0.0668
- 临界Z值:±1.960
由此我们可以得出与教材一致的结论:因为|Z| < 临界值(或P值>0.05),不能拒绝原假设。
2.2 t检验:打包机工作检验
第四题是方差未知时的单样本t检验典型案例:
# 样本数据 weights = np.array([99.3, 98.7, 100.5, 101.2, 98.3, 99.7, 99.5, 102.1, 100.5]) mu0 = 100 # 标准重量 # 使用scipy的ttest_1samp直接计算 t_stat, p_val = stats.ttest_1samp(weights, mu0) print(f"t统计量: {t_stat:.3f}") print(f"P值: {p_val:.4f}") # 获取临界t值 df = len(weights) - 1 # 自由度 t_critical = stats.t.ppf(1-alpha/2, df) print(f"临界t值: ±{t_critical:.3f}")输出结果:
- t统计量:-0.054
- P值:0.9586
- 临界t值:±2.306
这个结果验证了打包机工作正常的结论,因为统计量绝对值远小于临界值。
3. 双样本检验案例
3.1 独立样本t检验:装配时间比较
第十题是比较两种装配方法效率的双样本t检验问题:
# 两种方法的装配时间数据 method_A = np.array([...]) # 填入方法A的数据 method_B = np.array([...]) # 填入方法B的数据 # 使用scipy的ttest_ind进行独立样本t检验 t_stat, p_val = stats.ttest_ind(method_A, method_B, equal_var=True) print(f"t统计量: {t_stat:.3f}") print(f"P值: {p_val:.6f}") # 可视化两组数据分布 import matplotlib.pyplot as plt plt.boxplot([method_A, method_B], labels=['方法A', '方法B']) plt.ylabel('装配时间(分钟)') plt.title('两种装配方法比较') plt.show()3.2 比例检验:吸烟与气管炎关系
第十一题是典型的双比例检验案例:
from statsmodels.stats.proportion import proportions_ztest # 数据准备 count = np.array([43, 13]) # 患病人数 nobs = np.array([205, 134]) # 各组样本量 # 执行双比例Z检验 z_stat, p_val = proportions_ztest(count, nobs, alternative='larger') print(f"Z统计量: {z_stat:.3f}") print(f"P值: {p_val:.6f}")4. 方差分析与卡方检验
4.1 方差齐性检验:学习成绩比较
第十五题需要先检验方差齐性,再进行均值比较:
# 男生和女生的成绩方差 var_m = 56 var_f = 49 n_m = 25 n_f = 16 # F检验方差齐性 F = var_m / var_f p_val = stats.f.sf(F, n_m-1, n_f-1) print(f"F值: {F:.3f}") print(f"P值: {p_val:.4f}") # 确定方差齐性后,进行t检验 mean_m = 82 mean_f = 78 t_stat = (mean_m - mean_f)/np.sqrt((var_m/n_m)+(var_f/n_f)) df = n_m + n_f - 2 # 自由度 p_val = stats.t.sf(t_stat, df) print(f"t统计量: {t_stat:.3f}") print(f"P值: {p_val:.4f}")4.2 卡方检验:螺栓口径方差检验
第十四题的第二部分需要对总体方差进行检验:
# 参数设置 sigma0_sq = 0.03 # 规定方差 s_sq = 0.0375 # 样本方差 n = 80 # 样本量 # 计算卡方统计量 chi2_stat = (n-1)*s_sq/sigma0_sq p_val = stats.chi2.sf(chi2_stat, n-1) print(f"卡方统计量: {chi2_stat:.3f}") print(f"P值: {p_val:.4f}")5. 结果可视化与解读技巧
假设检验的结果可视化能极大增强理解:
def plot_test_result(stat, critical, test_type='two-sided'): """绘制检验统计量与拒绝域""" x = np.linspace(-4, 4, 1000) y = stats.norm.pdf(x) plt.plot(x, y, label='标准正态分布') plt.axvline(stat, color='r', linestyle='--', label='检验统计量') if test_type == 'two-sided': plt.axvline(critical, color='g', linestyle=':', label='临界值') plt.axvline(-critical, color='g', linestyle=':') fill_x = np.linspace(-4, -critical, 100) plt.fill_between(fill_x, stats.norm.pdf(fill_x), color='red', alpha=0.3) fill_x = np.linspace(critical, 4, 100) plt.fill_between(fill_x, stats.norm.pdf(fill_x), color='red', alpha=0.3) elif test_type == 'right': plt.axvline(critical, color='g', linestyle=':', label='临界值') fill_x = np.linspace(critical, 4, 100) plt.fill_between(fill_x, stats.norm.pdf(fill_x), color='red', alpha=0.3) else: # left plt.axvline(-critical, color='g', linestyle=':', label='临界值') fill_x = np.linspace(-4, -critical, 100) plt.fill_between(fill_x, stats.norm.pdf(fill_x), color='red', alpha=0.3) plt.title('假设检验结果可视化') plt.legend() plt.show() # 示例:绘制第一题的检验结果 plot_test_result(z_score, z_critical, 'two-sided')6. 常见问题与调试技巧
在实际应用中,经常会遇到各种问题:
检验方法选择错误:
- 方差已知用Z检验,未知用t检验
- 小样本(n<30)优先考虑t检验
单侧/双侧检验混淆:
# SciPy中单侧检验的调整 t_stat, p_val = stats.ttest_1samp(data, mu0) p_val_one_tailed = p_val / 2 # 对于单侧检验数据正态性不满足:
# 正态性检验 from scipy.stats import shapiro stat, p = shapiro(data) if p < alpha: print("数据不服从正态分布,考虑非参数检验")样本量极小时的应对:
- 考虑使用精确检验方法
- 或采用bootstrap重采样技术
注意:当P值接近显著性水平时,结论需要特别谨慎,可能需要考虑增加样本量或调整检验方法。
通过这六个章节的系统讲解,我们不仅用Python重现了教材中的所有假设检验案例,还增加了可视化展示和实用技巧。在实际数据分析工作中,这种将统计理论与编程实践相结合的能力,将使您从众多数据分析师中脱颖而出。