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

如何用Pandas分组绘制指定样式的堆叠柱状图?

实现Pandas分组堆叠并列柱状图的解决方案

需求说明

现有数据集包含日期、两类版本用户及对应花费,结构如下:

date_time   version_A   spend_A version_B   spend_B
2022-07-30  User1   39734.582   User1   15354.253
2022-07-30  User2   11720.6742  User2   3486.8551
... ... ... ... ...
2022-08-12  User5   111739.7095 User5   39797.8841

需要绘制的图表要求:

  • X轴为date_time
  • 每个日期对应两个并列的堆叠柱状图:分别展示spend_A和spend_B的总花费
  • 每个堆叠柱内按version_A(与version_B用户一一对应)的不同用户拆分,用颜色区分

问题分析

直接使用Pandas的plot(kind='bar', stacked=True)会将spend_A和spend_B堆叠到同一柱形中,无法实现并列效果;简单分组后的图表可读性差,需要调整数据结构并手动控制绘图逻辑。

解决方案

步骤1:数据整理与聚合

先将宽表转换为适合堆叠绘图的结构,再按日期、类别、用户聚合总花费:

import pandas as pd

# 拆分spend_A和spend_B数据并合并为长表
df_a = df[['date_time', 'version_A', 'spend_A']].rename(columns={'version_A': 'user', 'spend_A': 'amount'})
df_a['category'] = 'spend_A'

df_b = df[['date_time', 'version_B', 'spend_B']].rename(columns={'version_B': 'user', 'spend_B': 'amount'})
df_b['category'] = 'spend_B'

df_long = pd.concat([df_a, df_b], ignore_index=True)

# 按日期、类别、用户聚合求和
df_agg = pd.pivot_table(df_long, 
                        index='date_time', 
                        columns=['category', 'user'], 
                        values='amount', 
                        aggfunc='sum')

步骤2:绘制并列堆叠柱状图

使用Matplotlib手动控制柱子位置,实现spend_A和spend_B的并列堆叠效果:

import matplotlib.pyplot as plt

dates = df_agg.index.values
n_dates = len(dates)
width = 0.35  # 柱子宽度

fig, ax = plt.subplots(figsize=(12, 6))

# 绘制spend_A的堆叠柱(左列)
bottom_a = [0] * n_dates
for user in df_agg['spend_A'].columns:
    ax.bar(
        [i - width/2 for i in range(n_dates)],
        df_agg['spend_A'][user],
        width,
        bottom=bottom_a,
        label=f'spend_A - {user}'
    )
    bottom_a = [b + val for b, val in zip(bottom_a, df_agg['spend_A'][user])]

# 绘制spend_B的堆叠柱(右列)
bottom_b = [0] * n_dates
for user in df_agg['spend_B'].columns:
    ax.bar(
        [i + width/2 for i in range(n_dates)],
        df_agg['spend_B'][user],
        width,
        bottom=bottom_b,
        label=f'spend_B - {user}'
    )
    bottom_b = [b + val for b, val in zip(bottom_b, df_agg['spend_B'][user])]

# 配置图表样式
ax.set_xticks(range(n_dates))
ax.set_xticklabels(dates, rotation=45)
ax.set_xlabel('日期')
ax.set_ylabel('总花费')
ax.set_title('每日spend_A与spend_B用户堆叠花费对比')

# 调整图例位置避免遮挡
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left')

plt.tight_layout()
plt.show()

效果说明

执行上述代码后,每个日期下会生成两个并列的堆叠柱:

  • 左侧柱为spend_A的用户花费堆叠
  • 右侧柱为spend_B的用户花费堆叠
    不同用户用不同颜色区分,清晰展示各维度的花费分布。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 17:27:37