You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中Friedman检验及Dunn事后检验分析差异蛋白遇阻求助

问题:Friedman检验结合Dunn事后检验分析蛋白差异的代码报错排查及方法推荐

我想用Friedman检验识别有统计显著性的蛋白,数据集是多次试验汇总的中位数,包含两种独立培养基及各自对照组,收集了特定时间段内各培养基的蛋白含量,目标是对比两种培养基,找出含量有统计差异的蛋白。

我尝试先做Friedman检验,再用Dunn事后检验,但代码运行失败,希望帮忙排查问题,也欢迎推荐适合的其他统计方法。

原代码

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
from scipy.stats import friedmanchisquare
from scikit_posthocs import posthoc_dunn

# Sample data
data = {
    'Protein': ['Protein1', 'Protein2', 'Protein3', 'Protein4', 'Protein5'],
    'Control_Medium1': [1.0, 1.1, 1.2, 1.0, 1.3],
    'Control_Medium2': [1.1, 1.0, 1.1, 1.2, 1.0],
    'Medium1_T1': [1.5, 1.5, 1.8, 2.0, 1.6],
    'Medium1_T2': [1.2, 1.3, 1.7, 1.9, 2.1],
    'Medium1_T3': [1.1, 1.6, 1.9, 1.4, 1.7],
    'Medium2_T1': [0.1, 1.2, 1.7, 1.8, 1.5],
    'Medium2_T2': [0.2, 1.4, 1.8, 1.7, 1.9],
    'Medium2_T3': [0.3, 1.5, 1.3, 1.7, 1.4],
}

df = pd.DataFrame(data)

# Perform Friedman test
control_medium1 = df['Control_Medium1']
control_medium2 = df['Control_Medium2']
medium1_t1 = df['Medium1_T1']
medium1_t2 = df['Medium1_T2']
medium1_t3 = df['Medium1_T3']
medium2_t1 = df['Medium2_T1']
medium2_t2 = df['Medium2_T2']
medium2_t3 = df['Medium2_T3']

_, p_value = friedmanchisquare(control_medium1, control_medium2, medium1_t1, medium1_t2, medium1_t3,
                               medium2_t1, medium2_t2, medium2_t3)

# Print Friedman test result
print('Friedman Test:')
print('p-value:', p_value)

# Perform pairwise comparisons with posthoc test
data_for_posthoc = [medium1_t1, medium1_t2, medium1_t3, medium2_t1, medium2_t2, medium2_t3]
labels_for_posthoc = ['Medium1_T1', 'Medium1_T2', 'Medium1_T3', 'Medium2_T1', 'Medium2_T2', 'Medium2_T3']

posthoc_result = sp.posthoc_dunn(data_for_posthoc)

# Apply Bonferroni correction to p-values
alpha = 0.05
corrected_p_values = np.multiply(posthoc_result, len(posthoc_result.columns))

# Get the significantly different proteins
significant_proteins = []

for protein in df.columns[1:]:
    if any(corrected_p_values[protein] < alpha):
        significant_proteins.append(protein)

print('Significant Proteins:', significant_proteins)

代码问题排查

  • 导入引用错误:代码中使用sp.posthoc_dunn调用函数,但导入语句是from scikit_posthocs import posthoc_dunn,应直接使用posthoc_dunn,无需前缀sp.。
  • Friedman检验输入逻辑错误:scipy.stats.friedmanchisquare要求输入为同一受试对象的重复测量数据(行对应受试对象,列对应不同处理/时间点)。但当前数据行是蛋白,列是不同培养基/时间点,把所有蛋白的测量值混在一起做整体检验,不符合Friedman检验的配伍组设计逻辑——你的目标是找出不同培养基中含量有差异的蛋白,应该针对每个蛋白单独做检验。
  • 事后检验数据结构错误:posthoc_dunn需要结合试验设计的分组/区组信息,当前输入的是各列数据的列表,未考虑蛋白作为区组,且没有使用长格式数据,导致检验结果无法对应到蛋白层面。
  • 显著蛋白判断逻辑错误:corrected_p_values是培养基/时间点的两两比较矩阵,而非蛋白层面的结果,循环遍历df.columns[1:](培养基列)来筛选蛋白,逻辑完全错位。

修正后的代码示例

import numpy as np
import pandas as pd
from scipy.stats import friedmanchisquare
from scikit_posthocs import posthoc_dunn

# 样本数据
data = {
    'Protein': ['Protein1', 'Protein2', 'Protein3', 'Protein4', 'Protein5'],
    'Control_Medium1': [1.0, 1.1, 1.2, 1.0, 1.3],
    'Control_Medium2': [1.1, 1.0, 1.1, 1.2, 1.0],
    'Medium1_T1': [1.5, 1.5, 1.8, 2.0, 1.6],
    'Medium1_T2': [1.2, 1.3, 1.7, 1.9, 2.1],
    'Medium1_T3': [1.1, 1.6, 1.9, 1.4, 1.7],
    'Medium2_T1': [0.1, 1.2, 1.7, 1.8, 1.5],
    'Medium2_T2': [0.2, 1.4, 1.8, 1.7, 1.9],
    'Medium2_T3': [0.3, 1.5, 1.3, 1.7, 1.4],
}

df = pd.DataFrame(data)

alpha = 0.05
significant_proteins = []

# 针对每个蛋白单独分析
for _, row in df.iterrows():
    protein_name = row['Protein']
    # 获取该蛋白在所有处理组的测量值
    values = row[1:].values
    group_names = df.columns[1:]
    
    # 执行Friedman检验:每个蛋白作为一个受试对象,各处理组为重复测量
    _, p_val = friedmanchisquare(*values)
    
    if p_val < alpha:
        # 转成长格式数据用于事后检验
        protein_df = pd.DataFrame({
            'group': group_names,
            'value': values
        })
        # 执行Dunn事后检验,使用Bonferroni校正
        posthoc_results = posthoc_dunn(protein_df, val_col='value', group_col='group', p_adjust='bonferroni')
        
        # 检查Medium1与Medium2组间的两两比较是否存在显著差异
        medium1_groups = [g for g in group_names if 'Medium1' in g]
        medium2_groups = [g for g in group_names if 'Medium2' in g]
        has_diff = False
        
        for m1 in medium1_groups:
            for m2 in medium2_groups:
                if posthoc_results.loc[m1, m2] < alpha:
                    has_diff = True
                    break
            if has_diff:
                break
        
        if has_diff:
            significant_proteins.append(protein_name)

print('具有显著差异的蛋白:', significant_proteins)

适用统计方法推荐

  • 独立样本场景:如果不同培养基是独立培养体系(蛋白测量来自不同样本),Friedman检验不适用,建议使用Kruskal-Wallis H检验(非参数版单因素ANOVA),后续用Dunn或Tukey事后检验做两两比较。
  • 重复测量场景:如果是同一培养体系在不同时间点测量同一蛋白,Friedman检验是合适的,事后检验可选择Dunn检验或Conover检验。
  • 多检验校正:由于需要对多个蛋白进行检验,建议使用Bonferroni或FDR(错误发现率)校正整体α水平,降低假阳性概率。

内容的提问来源于stack exchange,提问作者planckton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 17:12:05