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

如何用Pandas实现分组柱状图+占比折线图?支持透视表/GroupBy

问题描述

给定数据集:

import pandas as pd

df = pd.DataFrame({
    'Vintage': ['2016Q1','2016Q1', '2016Q2','2016Q3','2016Q4','2016Q1', '2016Q2','2016Q2','2016Q2','2016Q3','2016Q4'], 
     'Model': ['A','A','A','A','A','B','B','B','B','B','B'],
     'Count': [1,1,1,1,1,1,1,1,1,1,1],
     'Case':[0,1,1,0,1,1,0,0,1,1,0],
})

对应的数据表:

VintageModelCountCase
02016Q1A10
12016Q1A11
22016Q2A11
32016Q3A10
42016Q4A11
52016Q1B11
62016Q2B10
72016Q2B10
82016Q2B11
92016Q3B11
102016Q4B10

需要完成两个任务:

  • 绘制分组柱状图,以Vintage为分组维度,Model作为颜色区分(hue);
  • 在同一图表中添加两条折线图,展示每个Model和Vintage下Case占Count的百分比(即Case/Count的比值)。

已实现第一个任务的代码:

dfp = df.pivot_table(index='Vintage', columns='Model', values='Count', aggfunc='sum')
dfp.plot(kind='bar', figsize=(8, 4), rot=45,  ylabel='Frequency', title="Vintages")

但无法在该透视表中完成占比计算并绘制折线图,尝试列间除法后格式不支持绘图。需解决:

  1. 无需创建额外表格完成占比计算与折线图绘制;
  2. 能否用groupby替代透视表完成全部任务?
解决方案

方法一:基于透视表扩展,无需额外表格

直接在绘图流程中完成计数柱状图绘制、占比计算与折线图叠加,通过双轴适配计数和百分比的数值范围:

import matplotlib.pyplot as plt

# 绘制计数柱状图
dfp_count = df.pivot_table(index='Vintage', columns='Model', values='Count', aggfunc='sum')
ax1 = dfp_count.plot(kind='bar', figsize=(8, 4), rot=45, ylabel='Frequency', title="Vintages", color=['#1f77b4', '#ff7f0e'])

# 计算Case/Count占比
dfp_ratio = df.pivot_table(index='Vintage', columns='Model', values='Case', aggfunc='sum') / dfp_count * 100

# 叠加折线图,使用右侧Y轴
ax2 = ax1.twinx()
dfp_ratio.plot(kind='line', marker='o', ax=ax2, ylabel='Case/Count Ratio (%)', color=['#1f77b4', '#ff7f0e'])

# 合并图例,避免重复
handles1, labels1 = ax1.get_legend_handles_labels()
handles2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(handles1 + handles2, labels1 + [f"{l} (%)" for l in labels2], loc='upper left')

plt.tight_layout()
plt.show()

方法二:用groupby替代透视表完成全部任务

通过groupby按Vintage和Model聚合,直接计算计数、占比后绘图:

import matplotlib.pyplot as plt

# 分组聚合计算总Count、总Case
grouped = df.groupby(['Vintage', 'Model']).agg(
    total_count=('Count', 'sum'),
    total_case=('Case', 'sum')
).reset_index()

# 计算占比百分比
grouped['case_ratio'] = grouped['total_case'] / grouped['total_count'] * 100

# 绘制柱状图
fig, ax1 = plt.subplots(figsize=(8, 4))
for model in grouped['Model'].unique():
    subset = grouped[grouped['Model'] == model]
    ax1.bar(subset['Vintage'], subset['total_count'], width=0.4, label=model, alpha=0.7)

# 叠加折线图
ax2 = ax1.twinx()
for model in grouped['Model'].unique():
    subset = grouped[grouped['Model'] == model]
    ax2.plot(subset['Vintage'], subset['case_ratio'], marker='o', label=f"{model} (%)", linewidth=2)

# 调整图表样式
ax1.set_ylabel('Frequency')
ax2.set_ylabel('Case/Count Ratio (%)')
ax1.set_title('Vintages')
ax1.tick_params(axis='x', rotation=45)

# 合并图例
handles1, labels1 = ax1.get_legend_handles_labels()
handles2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(handles1 + handles2, labels1 + labels2, loc='upper left')

plt.tight_layout()
plt.show()

说明

  • 两种方法均无需额外存储冗余表格,计算与绘图流程连贯;
  • 双轴设置解决了计数与百分比数值范围差异的问题,提升图表可读性;
  • groupby方法更灵活,便于后续扩展更多聚合逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 10:40:50