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

Pandas绘制双Y轴分组堆叠柱状图实现方案

双Y轴分组堆叠柱状图实现方案

原有代码无法实现需求的核心原因有两个:

  • 直接对groupby结果调用plot.bar()会为每个MainCategory单独生成独立画布,无法在同一坐标系下实现分组并排效果
  • 直接调用unstack()报错是因为没有先对SubCategory维度做聚合重排,多重索引结构不匹配matplotlib的绘图入参要求

完整实现代码

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# 读取CSV数据,跳过前2行注释头
data = pd.read_csv('failureEventStatistic_total_Top10.csv', sep=',', header=2)

# 提取所有主分类作为X轴刻度,固定排序
main_categories = sorted(data['MainCategory'].unique())
x_pos = np.arange(len(main_categories))
bar_width = 0.35  # 单组内两根柱子的宽度

# 构造透视表:行为主分类,列为子分类,值分别对应时长、事件数,空值补0
dur_pivot = data.pivot_table(
    index='MainCategory',
    columns='SubCategory',
    values='DurationH',
    aggfunc='sum'
).fillna(0).reindex(main_categories)

num_pivot = data.pivot_table(
    index='MainCategory',
    columns='SubCategory',
    values='Number',
    aggfunc='sum'
).fillna(0).reindex(main_categories)

# 创建画布与双Y轴
fig, ax_left = plt.subplots(figsize=(12, 7))
ax_right = ax_left.twinx()

# 绘制左Y轴对应的DurationH堆叠柱,位置在组内左偏移
bottom_dur = np.zeros(len(main_categories))
for sub_cat in dur_pivot.columns:
    ax_left.bar(
        x_pos - bar_width/2,
        dur_pivot[sub_cat],
        bar_width,
        bottom=bottom_dur,
        label=f'时长-{sub_cat}'
    )
    bottom_dur += dur_pivot[sub_cat].values

# 绘制右Y轴对应的Number堆叠柱,位置在组内右偏移,加斜纹做视觉区分
bottom_num = np.zeros(len(main_categories))
for sub_cat in num_pivot.columns:
    ax_right.bar(
        x_pos + bar_width/2,
        num_pivot[sub_cat],
        bar_width,
        bottom=bottom_num,
        label=f'次数-{sub_cat}',
        hatch='//'
    )
    bottom_num += num_pivot[sub_cat].values

# 坐标轴配置
ax_left.set_xlabel('主分类')
ax_left.set_ylabel('累计时长 [h]', color='#1f77b4')
ax_left.tick_params(axis='y', labelcolor='#1f77b4')
ax_left.set_xticks(x_pos, main_categories, rotation=45)

ax_right.set_ylabel('累计事件次数', color='#ff7f0e')
ax_right.tick_params(axis='y', labelcolor='#ff7f0e')

# 合并双轴图例,放在画布外侧避免遮挡
handles_l, labels_l = ax_left.get_legend_handles_labels()
handles_r, labels_r = ax_right.get_legend_handles_labels()
ax_left.legend(
    handles_l + handles_r,
    labels_l + labels_r,
    bbox_to_anchor=(1.18, 1),
    loc='upper left'
)

plt.tight_layout()
plt.show()

实现效果说明

  • X轴按MainCategory做分组刻度,每个分组下左右并排两根柱子,分别对应时长、事件数两个指标
  • 每根柱子内部按SubCategory维度分层堆叠,完全匹配需求
  • 双Y轴分别适配两个量纲差异较大的指标,不会出现小数值被压缩看不到的问题
  • 事件数系列柱子增加斜纹填充,和时长系列做明确视觉区分,避免同子分类颜色相近造成混淆

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 18:57:25