如何基于同分组变量的两个DataFrame绘制带标准差的误差棒图?
绘制喂养组-处理前后指标的误差棒图
第一步:数据格式转换
你手头的df_media和df_desv是宽格式,必须转成长格式才能方便绘图,让每个观测值对应「喂养组、指标名称、处理阶段、均值、标准差」:
import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns # 先确保DataFrame的行索引是喂养组名称(比如["组1", "组2"]),如果没设置,执行: # df_media.index = ["组1", "组2"] # df_desv.index = ["组1", "组2"] # 转长格式并合并均值与标准差 media_long = df_media.reset_index().melt(id_vars="index", var_name="full_metric", value_name="mean") desv_long = df_desv.reset_index().melt(id_vars="index", var_name="full_metric", value_name="std") df_combined = pd.merge(media_long, desv_long, on=["index", "full_metric"]) # 拆分指标名称和处理阶段(比如把"LDH1"拆成"LDH"和"处理前") df_combined["喂养组"] = df_combined["index"] df_combined["指标"] = df_combined["full_metric"].str.extract(r'([A-Za-z]+)') df_combined["处理阶段"] = df_combined["full_metric"].str.replace(r'[A-Za-z]+', '', regex=True).replace({"1": "处理前", "2": "处理后"}) # 清理冗余列 df_combined = df_combined.drop(columns=["index", "full_metric"])
第二步:绘图(两种实用方案)
方案1:单图汇总所有指标
适合快速对比所有指标在不同喂养组、不同处理阶段的差异:
plt.figure(figsize=(16, 8)) bar_width = 0.2 x = np.arange(len(df_combined["喂养组"].unique())) metrics = df_combined["指标"].unique() stages = df_combined["处理阶段"].unique() # 循环绘制每个指标+处理阶段的条形和误差棒 for i, metric in enumerate(metrics): for j, stage in enumerate(stages): subset = df_combined[(df_combined["指标"] == metric) & (df_combined["处理阶段"] == stage)] pos = x + i*len(stages)*bar_width + j*bar_width plt.bar(pos, subset["mean"], width=bar_width, label=f"{metric}-{stage}") plt.errorbar(pos, subset["mean"], yerr=subset["std"], fmt="none", c="black", capsize=4) # 配置图表元素 plt.xticks(x + bar_width*(len(metrics)*len(stages)-1)/2, df_combined["喂养组"].unique()) plt.xlabel("喂养组") plt.ylabel("指标均值") plt.legend(bbox_to_anchor=(1.02, 1), loc="upper left", title="指标-处理阶段") plt.tight_layout() plt.show()
方案2:子图分指标展示
每个指标单独一个子图,避免图表拥挤,更清晰地对比喂养组的处理前后数据:
g = sns.catplot( data=df_combined, x="喂养组", y="mean", hue="处理阶段", col="指标", kind="bar", yerr=df_combined["std"], capsize=5, col_wrap=3, # 每行显示3个子图,可根据指标数量调整 figsize=(15, 12) ) # 美化布局和标签 g.set_axis_labels("喂养组", "指标均值") g.set_titles("{col_name}") g.legend.set_title("处理阶段") plt.tight_layout() plt.show()
内容的提问来源于stack exchange,提问作者José
相关产品推荐
相关产品推荐

