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

如何扩展Matplotlib分组柱状图以展示全季度Budget与Actual数据

修改代码实现全季度分组柱状图

核心修改思路

  1. 用循环遍历Q1-Q4四个季度,避免重复编写柱状图绘制代码
  2. 计算每个季度柱子的偏移量,确保同一部门下的季度柱子有序排列、不重叠
  3. 动态适配部门数量,替换硬编码的数值
  4. 优化图例与布局,提升图表可读性

修改后的完整代码(两种实现方式)

方式一:基于原数据结构直接循环

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

df = pd.read_excel(file)

cols = df['Dept.']
df = df.T
df.columns = cols
df = df.tail(-1)  # 移除转置后的原表头行

# 基础配置
n_depts = len(cols)
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
single_bar_width = 0.1
colors = {'Actual': 'cornflowerblue', 'Budget': 'cornflowerblue'}
alphas = {'Actual': 1, 'Budget': 0.2}

x = np.arange(n_depts)

# 循环绘制每个季度的Actual和Budget柱子
for idx, quarter in enumerate(quarters):
    # 计算当前季度的整体偏移量,让柱子均匀分布在部门刻度两侧
    quarter_offset = (idx - 1.5) * 2 * single_bar_width
    # 绘制Actual数据
    plt.bar(
        x + quarter_offset,
        df.loc[f'{quarter} Actual'],
        width=single_bar_width,
        color=colors['Actual'],
        alpha=alphas['Actual'],
        label=f'{quarter} Actual' if idx == 0 else ""
    )
    # 绘制Budget数据
    plt.bar(
        x + quarter_offset + single_bar_width,
        df.loc[f'{quarter} Budget'],
        width=single_bar_width,
        color=colors['Budget'],
        alpha=alphas['Budget'],
        label=f'{quarter} Budget' if idx == 0 else ""
    )

# 图表样式配置
plt.xticks(x, cols, rotation=45)
plt.legend(title='Quarter & Type')
plt.title('Q1-Q4 Budget vs Actual by Department')
plt.xlabel('Department')
plt.ylabel('Amount')
plt.tight_layout()  # 自动调整布局,避免标签截断

plt.show()

方式二:数据重塑为长格式(更灵活)

如果后续需要扩展更多季度/指标,推荐这种方式:

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

df = pd.read_excel(file)

# 将宽表转为长格式,方便分组处理
df_melt = df.melt(id_vars='Dept.', var_name='Category', value_name='Amount')
# 拆分季度和指标类型(Budget/Actual)
df_melt[['Quarter', 'Type']] = df_melt['Category'].str.split(' ', expand=True)

# 基础配置
n_depts = len(df['Dept.'])
quarters = df_melt['Quarter'].unique()
types = df_melt['Type'].unique()
single_bar_width = 0.1

x = np.arange(n_depts)

# 循环绘制每个季度、每个类型的柱子
for q_idx, quarter in enumerate(quarters):
    for t_idx, typ in enumerate(types):
        # 计算当前柱子的偏移量
        bar_offset = (q_idx * len(types) + t_idx - (len(quarters)*len(types)-1)/2) * single_bar_width
        # 筛选对应数据
        filtered_data = df_melt[(df_melt['Quarter'] == quarter) & (df_melt['Type'] == typ)]
        # 绘制柱子
        plt.bar(
            x + bar_offset,
            filtered_data['Amount'],
            width=single_bar_width,
            label=f'{quarter} {typ}' if q_idx == 0 else "",
            color='cornflowerblue',
            alpha=1 if typ == 'Actual' else 0.2
        )

# 图表样式配置
plt.xticks(x, df['Dept.'], rotation=45)
plt.legend(title='Quarter & Type')
plt.title('Q1-Q4 Budget vs Actual by Department')
plt.xlabel('Department')
plt.ylabel('Amount')
plt.tight_layout()

plt.show()

关键修改点说明

  • 循环遍历季度:避免重复编写四次plt.bar,代码更简洁易维护
  • 动态偏移计算:确保同一部门下的8个柱子(4季度×2类型)均匀分布,不会重叠
  • 动态部门数量:用len(cols)代替硬编码的4,适配任意数量的部门
  • 图例优化:仅在第一次循环时添加图例标签,避免重复显示
  • 布局调整:plt.tight_layout()自动调整图表元素位置,防止x轴部门标签被截断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 21:50:39