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

如何基于DataFrame的subtype列绘制Mann-Whitney U检验图并解决报错

解决Mann-Whitney U检验多组比较及绘图问题

问题概述

你作为Python统计新手,希望基于包含normal、KIRP、KIRC、KICH的subtype列,绘制Mann-Whitney U检验(Wilcoxon秩和检验)相关的箱线图,但现有代码触发类型错误,且后续逻辑存在问题。

报错原因分析

  1. mannwhitneyu仅支持两样本比较:你直接传入4个DataFrame,导致第三个参数被误识别为use_continuity(要求布尔值),而实际传入的是DataFrame,触发TypeError: unhashable type: 'DataFrame'。
  2. 多组U值计算逻辑错误:U2 = nnormal*nkirp*nkirc*nkich - U1仅适用于两样本场景,多组无此公式。
  3. 绘图参数无效:px.box(_, y="pnorm")中_不是有效数据框,pnorm也不是数据框列名,无法生成图表。

修正后的完整代码

以下代码实现两两Mann-Whitney U检验并绘制带显著性标记的箱线图(匹配你提供的示例图风格):

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from scipy.stats import mannwhitneyu
from itertools import combinations

# 假设df是你的原始数据集
# 1. 数据预处理:选择目标特征并转为长格式(以第一个特征列为例,可替换为具体列名)
target_feature = df.columns[7]  # 对应你代码中的iloc[:,7]
plot_data = df[["subtype", target_feature]].rename(columns={target_feature: "expression"})

# 2. 执行两两Mann-Whitney U检验
groups = ["normal", "KIRP", "KIRC", "KICH"]
pairwise_pvalues = []
# 生成所有组间两两组合,若仅需normal vs 肿瘤组,可替换为[("normal", "KIRP"), ("normal", "KIRC"), ("normal", "KICH")]
for group_a, group_b in combinations(groups, 2):
    data_a = plot_data[plot_data["subtype"] == group_a]["expression"]
    data_b = plot_data[plot_data["subtype"] == group_b]["expression"]
    # 双侧检验,使用精确方法计算p值
    _, p_val = mannwhitneyu(data_a, data_b, alternative="two-sided", method="exact")
    pairwise_pvalues.append({"group1": group_a, "group2": group_b, "p_value": p_val})

# 3. 绘制箱线图
fig = px.box(
    plot_data,
    x="subtype",
    y="expression",
    color="subtype",
    title=f"{target_feature} 在不同亚型中的分布(Mann-Whitney U检验)",
    labels={"expression": "表达量", "subtype": "亚型"}
)

# 4. 添加显著性标记
y_upper = plot_data["expression"].max() * 1.1  # 标记起始位置
# 定义显著性规则
def sig_marker(p):
    if p < 0.001:
        return "***"
    elif p < 0.01:
        return "**"
    elif p < 0.05:
        return "*"
    else:
        return "ns"

# 遍历检验结果,绘制连接线和标记
for idx, result in enumerate(pairwise_pvalues):
    # 获取两组在x轴的索引位置
    x_idx1 = groups.index(result["group1"])
    x_idx2 = groups.index(result["group2"])
    sig = sig_marker(result["p_value"])
    # 绘制连接两组的横线
    fig.add_trace(
        go.Scatter(
            x=[x_idx1, x_idx1, x_idx2, x_idx2],
            y=[y_upper + idx*0.05*y_upper, y_upper + idx*0.05*y_upper + 0.02*y_upper,
               y_upper + idx*0.05*y_upper + 0.02*y_upper, y_upper + idx*0.05*y_upper],
            mode="lines",
            line=dict(color="black", width=1),
            showlegend=False
        )
    )
    # 添加显著性标记文本
    fig.add_annotation(
        x=(x_idx1 + x_idx2)/2,
        y=y_upper + idx*0.05*y_upper + 0.02*y_upper,
        text=sig,
        showarrow=False,
        font=dict(size=12)
    )

# 调整y轴范围,确保标记完整显示
fig.update_layout(yaxis_range=[plot_data["expression"].min()*0.9, y_upper*1.2])
fig.show()

代码说明

  1. 数据格式转换:将宽格式数据转为长格式,符合Plotly箱线图的输入要求。
  2. 两两检验逻辑:使用itertools.combinations生成所有组间组合,对每组执行Mann-Whitney U检验。若仅需比较正常组与肿瘤组,可直接指定组合列表。
  3. 显著性标记:根据p值大小生成对应星号标记,并在箱线图上方绘制连接线,清晰展示组间差异显著性。
  4. 批量处理扩展:若需对iloc[:,7:-2]的所有特征批量绘图,可循环遍历列名,重复上述绘图逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 14:35:20