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

如何为Pandas+Matplotlib绘制的分组柱状图添加次级嵌套分组

嵌套分组柱状图实现方案

要实现按Person、测试组、子测试的三级嵌套分组柱状图,需要先将宽表转为长表拆分分组维度,再手动计算每个柱子的x轴位置绘制,完整实现代码如下:

import pandas as pd
import matplotlib.pyplot as plt

# 原始数据
df=pd.DataFrame({
    'run-1a':[0.3, 0.3, 0.4, 0.4], 
    'run-1b':[0.3, 0.3, 0.4, 0.5],
    'run-2a':[0.7, 0.9, 0.8, 0.9],
    'run-2b':[0.2, 0.3, 0.5, 0.5], 
    'Person':["person1","person2","person3","person4"]
})

# 1. 数据预处理:拆分两级分组维度
df_melt = df.melt(id_vars='Person', var_name='run_id', value_name='score')
# 拆分主分组(run-1/run-2)和子分组(a/b)
df_melt['main_group'] = df_melt['run_id'].str.slice(0, -1)
df_melt['sub_group'] = df_melt['run_id'].str.slice(-1)

# 2. 配置绘图参数
bar_width = 0.18  # 单个柱子宽度
sub_gap = 0.02    # 同主分组下子柱子间距
main_gap = 0.3    # 同一个Person下两个主分组的间距
person_gap = 1.2  # 不同Person之间的间距
color_map = {'run-1a':'b', 'run-1b':'lightskyblue', 'run-2a':'g', 'run-2b':'lightgreen'}

persons = df['Person'].unique()
main_groups = ['run-1', 'run-2']
sub_groups = ['a', 'b']

# 计算每个Person的基准x坐标
person_base_x = {p:i * (2*(bar_width+sub_gap) + main_gap + person_gap) for i,p in enumerate(persons)}

fig, ax = plt.subplots(figsize=(10,5))

# 3. 循环绘制每个柱子
bars = []
labels = []
for person in persons:
    base_x = person_base_x[person]
    for main_idx, main_g in enumerate(main_groups):
        # 计算当前主分组的基准偏移
        main_offset = main_idx * (2*(bar_width+sub_gap) + main_gap)
        for sub_idx, sub_g in enumerate(sub_groups):
            run_id = f"{main_g}{sub_g}"
            # 计算当前柱子的x坐标
            x = base_x + main_offset + sub_idx*(bar_width + sub_gap)
            # 取对应数值
            val = df_melt[(df_melt['Person']==person) & (df_melt['run_id']==run_id)]['score'].values[0]
            # 画柱子
            bar = ax.bar(x, val, width=bar_width, color=color_map[run_id])
            # 仅第一次添加对应图例
            if run_id not in labels:
                bars.append(bar)
                labels.append(run_id)

# 4. 调整轴和图例
ax.set_xticks([person_base_x[p] + (2*(bar_width+sub_gap) + main_gap)/2 for p in persons])
ax.set_xticklabels(persons, rotation='horizontal')
ax.legend(bars, labels, loc='center left', bbox_to_anchor=(1, 0.5))
plt.tight_layout()
plt.show()

运行上述代码即可实现你需要的嵌套分组效果:每个Person对应两个大组,分别是run-1组(含run-1a、run-1b两个蓝色系柱子)和run-2组(含run-2a、run-2b两个绿色系柱子),组间有明显间距区分层级。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 23:36:08