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

如何基于多级透视表创建堆叠柱状图

解决方案:实现每月分年份的堆叠柱状图

要实现你需要的「每个月对应3个年份柱子,每个柱子内堆叠casual和member数据」的效果,我们可以通过调整透视表结构或使用Seaborn手动绘制堆叠柱两种方式实现,以下是具体步骤:

方法一:调整透视表结构,用Pandas直接绘图

你的原始透视表列层级是(year, usertype),我们可以通过重塑数据,将year移到索引层级,让usertype作为列,这样就能直接绘制出符合需求的堆叠柱状图:

# 重塑透视表:将year从列层级移到索引层级,usertype作为列
pivot_reshaped = pivotCust.stack(level='year').unstack(level='usertype')

# 绘制堆叠柱状图
ax = pivot_reshaped.plot(kind='bar', stacked=True, figsize=(17,10))

# 优化图表样式
ax.set_xlabel('月份')
ax.set_ylabel('出行次数')
ax.set_title('各年份不同用户类型的月度出行次数(堆叠柱状图)')
# 将图例移到图表外侧,避免遮挡
ax.legend(title='用户类型', bbox_to_anchor=(1.05, 1), loc='upper left')

效果说明

  • X轴会显示(月份, 年份)的组合,同一个月份的3个年份柱子会并排显示
  • 每个柱子内部会堆叠casual和member的数据,直观展示单年份内不同用户类型的占比

方法二:使用Melt转换长格式,结合Seaborn手动绘制

如果更偏好Seaborn的风格,可以先将透视表转换为长格式,再手动实现堆叠效果:

import seaborn as sns
import matplotlib.pyplot as plt

# 将透视表转换为长格式
df_melted = pivotCust.reset_index().melt(
    id_vars='month', 
    var_name=['year', 'usertype'], 
    value_name='count'
)

# 设置绘图风格
sns.set_style("whitegrid")
fig, ax = plt.subplots(figsize=(17,10))

# 定义柱子宽度和年份列表
width = 0.25
years = df_melted['year'].unique()
months = df_melted['month'].unique()

# 遍历每个年份,绘制堆叠柱
for idx, year in enumerate(years):
    # 筛选当前年份的两类用户数据
    casual_data = df_melted[(df_melted['year'] == year) & (df_melted['usertype'] == 'casual')].set_index('month')['count']
    member_data = df_melted[(df_melted['year'] == year) & (df_melted['usertype'] == 'member')].set_index('month')['count']
    
    # 绘制casual柱子(底层)
    ax.bar(
        [x + idx*width for x in range(len(months))], 
        casual_data, 
        width=width, 
        label=f'{year} casual'
    )
    # 绘制member柱子(堆叠在casual上方)
    ax.bar(
        [x + idx*width for x in range(len(months))], 
        member_data, 
        bottom=casual_data, 
        width=width, 
        label=f'{year} member'
    )

# 调整X轴标签和刻度
ax.set_xticks([x + width for x in range(len(months))])
ax.set_xticklabels(months)

# 设置图表标签和图例
ax.set_xlabel('月份')
ax.set_ylabel('出行次数')
ax.set_title('各年份不同用户类型的月度出行次数')
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left')

plt.tight_layout()
plt.show()

效果说明

  • 该方法完全手动控制柱子的位置和堆叠逻辑,灵活性更高
  • 同样实现「每月3个年份柱子,每个柱子堆叠两类用户」的需求,且Seaborn的样式更美观

方法三:拆分年份单独绘图(最直观的手动方式)

如果你希望更清晰地控制每个年份的柱子位置,可以直接拆分每个年份的透视表部分,分别绘制:

# 拆分出每个年份的子透视表
df_2019 = pivotCust['2019']
df_2020 = pivotCust['2020']
df_2021 = pivotCust['2021']

# 创建画布
fig, ax = plt.subplots(figsize=(17,10))

# 分别绘制三个年份的堆叠柱,设置不同的位置偏移实现并排
df_2019.plot(kind='bar', stacked=True, width=0.25, position=0, ax=ax, label=['2019 casual', '2019 member'])
df_2020.plot(kind='bar', stacked=True, width=0.25, position=1, ax=ax, label=['2020 casual', '2020 member'])
df_2021.plot(kind='bar', stacked=True, width=0.25, position=2, ax=ax, label=['2021 casual', '2021 member'])

# 优化图表
ax.set_xlabel('月份')
ax.set_ylabel('出行次数')
ax.set_title('各年份不同用户类型的月度出行次数')
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left')

plt.tight_layout()
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 15:27:11