如何为多层表头DataFrame绘制指定格式的柱状图?
双层表头DataFrame的柱状图绘制方案
数据转换优化
你用df.T.melt(ignore_index=False)的方向没问题,但需要调整转换逻辑,让数据结构更适配绘图需求。先把原始双层表头的DataFrame转成长格式,完整保留层级信息:
import pandas as pd import matplotlib.pyplot as plt import seaborn as sns # 构造原始DataFrame data = {('Case1', 'A'): {'One': 0.96396415, 'Two': 0.832049574, 'Three': 0.636568627, 'Four': 0.765846157},('Case1', 'B'): {'One': 0.257496625, 'Two': 0.984418254, 'Three': 0.018891398, 'Four': 0.440278509},('Case1', 'C'): {'One': 0.512732941, 'Two': 0.622697929, 'Three': 0.731555346, 'Four': 0.031419349},('Case2', 'A'): {'One': 0.736783294, 'Two': 0.460765675, 'Three': 0.078558864, 'Four': 0.566186283},('Case2', 'B'): {'One': 0.921473211, 'Two': 0.274749932, 'Three': 0.312766018, 'Four': 0.159229808},('Case2', 'C'): {'One': 0.146389032, 'Two': 0.893299471, 'Three': 0.536288712, 'Four': 0.775763286},('Case3', 'A'): {'One': 0.351607026, 'Two': 0.041402396, 'Three': 0.924265706, 'Four': 0.639154727},('Case3', 'B'): {'One': 0.966538215, 'Two': 0.658236148, 'Three': 0.473447279, 'Four': 0.545974617},('Case3', 'C'): {'One': 0.036585457, 'Two': 0.279443317, 'Three': 0.407991168, 'Four': 0.101083315}} df = pd.DataFrame(data=data) # 转换为适配绘图的长格式 df_long = df.stack(level=0).reset_index() df_long.columns = ['Row', 'Case', 'A', 'B', 'C'] # 进一步拆分为更通用的绘图格式 df_plot = df_long.melt(id_vars=['Row', 'Case'], var_name='Category', value_name='Value')
两种绘图方案
方案1:合并绘制(类似Excel分组柱状图)
将所有Case整合到同一视图,按行索引(One/Two/Three/Four)分组,展示不同Case的A/B/C类别数据:
# 单图分组展示 plt.figure(figsize=(12, 6)) sns.barplot(data=df_plot, x='Row', y='Value', hue='Case', palette='viridis', errorbar=None) plt.title('所有Case的分组柱状图') plt.tight_layout() plt.show() # 按A/B/C拆分子图展示 g = sns.FacetGrid(df_plot, col='Category', col_wrap=3, height=4) g.map(sns.barplot, 'Row', 'Value', 'Case', palette='viridis', errorbar=None) g.add_legend() plt.tight_layout() plt.show()
方案2:每个Case单独绘图
循环遍历每个Case,生成独立的柱状图,便于单独分析:
cases = df_plot['Case'].unique() for case in cases: case_data = df_plot[df_plot['Case'] == case] plt.figure(figsize=(8, 5)) sns.barplot(data=case_data, x='Row', y='Value', hue='Category', palette='coolwarm', errorbar=None) plt.title(f'{case} 数据柱状图') plt.ylabel('数值') plt.tight_layout() plt.show()
关键说明
stack(level=0)将一级表头(Case1/2/3)转为行索引,再通过reset_index展开,确保层级信息完整保留melt转换时保留Row和Case作为标识变量,让后续绘图能精准分组- 使用seaborn比matplotlib原生API更易实现类似Excel的分组效果,也能快速拆分多子图
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

