如何用Python对生物医学实验曲线进行统计差异分析?
统计方法选择与Python实现
针对你在生物医学实验中比较两条时间序列曲线差异的需求,以下是适合的统计方法及对应的Python实现:
一、核心统计方法选择
1. 重复测量方差分析(Repeated Measures ANOVA)
- 适用场景:同一批生物学重复样本在不同时间点被重复测量(比如同一处理组的6个样本,在时间1-5都有检测值)。可同时分析组间差异(蓝/橙曲线)、时间效应,以及两者的交互效应(比如两组随时间变化的趋势是否不同)。
- 前提:数据需满足正态性、方差齐性,以及球形假设(若不满足,结果会自动给出Greenhouse-Geisser校正值)。
2. 双因素方差分析(Two-Way ANOVA)
- 适用场景:不同样本在不同时间点测量(独立样本)。将「组(蓝/橙)」和「时间点」作为两个固定因素,分析组间的整体差异、时间对数值的影响,以及组与时间的交互作用。
3. 事后检验(Post-hoc Tests)
- 若ANOVA得出整体显著的结果,需要用事后检验定位具体哪些时间点两组存在差异,常用Tukey's HSD检验(参数方法)或Dunn's检验(非参数方法)。
4. 非参数替代方法
- 若数据不满足正态性或方差齐性(生物实验常见),用:
- Friedman检验:替代重复测量ANOVA,用于分析同一组样本在不同时间/处理下的差异。
- Kruskal-Wallis检验:替代双因素ANOVA,用于独立样本的组间差异分析。
二、Python代码实现
以下代码基于statsmodels和scipy库,模拟生物实验常见的重复测量场景(每组6个生物学重复,时间点1-5):
1. 导入依赖库
import numpy as np import pandas as pd from statsmodels.formula.api import ols from statsmodels.stats.anova import AnovaRM from statsmodels.stats.multicomp import pairwise_tukeyhsd from scipy.stats import kruskal, shapiro, levene
2. 模拟实验数据
np.random.seed(42) # 固定随机种子,结果可复现 time_points = [1, 2, 3, 4, 5] n_bio_reps = 6 # 生物学重复数 # 生成两组数据:蓝色组均值随时间上升更快,橙色组均值较低 blue_data = np.array([np.random.normal(loc=10 + t*2, scale=1, size=n_bio_reps) for t in time_points]).T orange_data = np.array([np.random.normal(loc=8 + t*1.5, scale=1, size=n_bio_reps) for t in time_points]).T # 整理成statsmodels需要的长格式DataFrame df = pd.DataFrame() for rep_idx in range(n_bio_reps): for t_idx, t in enumerate(time_points): # 蓝色组数据行 df = pd.concat([df, pd.DataFrame({ 'time': t, 'value': blue_data[rep_idx, t_idx], 'group': 'blue', 'replicate': f'rep_{rep_idx+1}' }, index=[0])], ignore_index=True) # 橙色组数据行 df = pd.concat([df, pd.DataFrame({ 'time': t, 'value': orange_data[rep_idx, t_idx], 'group': 'orange', 'replicate': f'rep_{rep_idx+1}' }, index=[0])], ignore_index=True)
3. 数据前提检验
先验证正态性和方差齐性:
# 正态性检验(Shapiro-Wilk) for group in ['blue', 'orange']: for t in time_points: subset = df[(df['group'] == group) & (df['time'] == t)]['value'] stat, p = shapiro(subset) print(f"组{group} 时间点{t} 正态性检验:p值={p:.4f}") # 方差齐性检验(Levene) for t in time_points: subset_blue = df[(df['group'] == 'blue') & (df['time'] == t)]['value'] subset_orange = df[(df['group'] == 'orange') & (df['time'] == t)]['value'] stat, p = levene(subset_blue, subset_orange) print(f"时间点{t} 方差齐性检验:p值={p:.4f}")
4. 重复测量ANOVA分析
# 拟合重复测量ANOVA模型 anova_rm = AnovaRM(df, depvar='value', subject='replicate', within=['time', 'group']) rm_results = anova_rm.fit() print("重复测量ANOVA结果:") print(rm_results.summary())
5. 事后检验:定位差异时间点
# 对每个时间点单独做组间比较(Tukey's HSD) for t in time_points: time_subset = df[df['time'] == t] tukey_test = pairwise_tukeyhsd(endog=time_subset['value'], groups=time_subset['group'], alpha=0.05) print(f"\n=== 时间点{t} 组间比较结果 ===") print(tukey_test.summary())
6. 非参数分析(Kruskal-Wallis)
如果数据不满足参数检验前提,用非参数方法:
for t_idx, t in enumerate(time_points): stat, p = kruskal(blue_data[:, t_idx], orange_data[:, t_idx]) print(f"\n时间点{t} Kruskal-Wallis检验:统计量={stat:.2f}, p值={p:.4f}") if p < 0.05: print(f" → 该时间点两组存在显著差异(p<0.05)")
三、关键注意事项
- 生物实验中必须基于生物学重复做统计分析,技术重复只能用于计算均值/标准差,不能作为统计检验的样本。
- 标准差无重叠只是直观判断,不能替代统计检验:样本量小时,标准差重叠也可能存在显著差异;反之,标准差不重叠也可能因样本量不足无统计显著性。
- 若你的数据是独立样本(不同时间点用不同样本),改用双因素ANOVA:
model = ols('value ~ C(group) + C(time) + C(group):C(time)', data=df).fit() anova_table = sm.stats.anova_lm(model, typ=2) print(anova_table)
内容的提问来源于stack exchange,提问作者Phil
相关产品推荐
相关产品推荐

