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

Matplotlib:同年份多系列柱状图并列且年份间留间隔实现求助

问题与解决方案

需求

实现同一年份下不同store_type的柱状图并列展示,且不同年份的柱状图组之间保留明显间隙。

原代码问题分析

原代码中x轴位置的计算直接按年份索引乘以月份数,导致年份组之间无间隙,且同一年份内不同store_type的柱状图未实现并列布局。

修改后的代码

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

def plot_monthly_multiple_store2():
    df = order_merged.multi_store_monthly_count([2020,2021], [1,2,3,4], ['Crizac','Ucol'])
    df['year'] = df['date_added'].dt.year
    df['month'] = df['date_added'].dt.month

    # 按年份、月份、门店类型统计订单数
    count_df = df.groupby(['year', 'month', 'store_type'])['order_id'].count().reset_index()

    # 透视数据,行是(年份,月份),列是门店类型
    pivot_df = pd.pivot_table(count_df, values='order_id', index=['year', 'month'], columns=['store_type'], fill_value=0)

    fig, ax = plt.subplots(figsize=(10, 5))
    colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd']

    # 按同月份内的门店数量分配柱子宽度
    num_stores = len(pivot_df.columns)
    width = 0.7 / num_stores
    # 年份组之间的间隙值,可按需调整
    gap_between_years = 0.5
    num_months_per_year = len(pivot_df.index.levels[1])

    for year_idx, year in enumerate(pivot_df.index.levels[0]):
        # 计算当前年份组的基础x轴位置,加入年份间隙
        base_x = year_idx * (num_months_per_year + gap_between_years)
        # 遍历每个月份
        for month_idx, month in enumerate(pivot_df.loc[year].index):
            # 遍历每个门店类型,计算单根柱子的x位置
            for store_idx, store_type in enumerate(pivot_df.columns):
                x_pos = base_x + month_idx + store_idx * width
                count_val = pivot_df.loc[(year, month), store_type]
                ax.bar(x_pos, count_val, width=width, color=colors[store_idx], alpha=0.7, edgecolor='black', linewidth=0.5, 
                       label=store_type if year_idx == 0 and month_idx == 0 else None)
                # 添加柱子顶部的数值标签
                ax.text(x_pos + width/2, count_val, str(count_val), ha='center', va='bottom', fontsize=8)

    # 调整x轴刻度位置,放在每个月份所有柱子的中间
    tick_positions = []
    tick_labels = []
    for year_idx, year in enumerate(pivot_df.index.levels[0]):
        base_x = year_idx * (num_months_per_year + gap_between_years)
        for month_idx, month in enumerate(pivot_df.loc[year].index):
            tick_pos = base_x + month_idx + (num_stores * width)/2
            tick_positions.append(tick_pos)
            tick_labels.append(f"{calendar.month_abbr[month]}\n{year}")

    ax.set_xticks(tick_positions)
    ax.set_xticklabels(tick_labels, fontsize=8)

    ax.set_xlabel('年份-月份', fontsize=12)
    ax.set_ylabel('订单数量', fontsize=12)
    ax.set_title('各月份不同门店类型的订单数量', fontsize=14)

    ax.legend(loc='upper left', bbox_to_anchor=(1.0, 1.0))
    plt.tight_layout()
    plt.show()

修改说明

  • 柱子宽度适配:按同月份内的门店数量分配宽度,确保同月份的多门店柱子能并列排布
  • 年份间隙控制:通过gap_between_years参数自定义不同年份组之间的空白距离,数值越大间隙越宽
  • x轴位置重构:每个年份组设置独立的基础x坐标,同月份内的不同门店柱子依次偏移宽度,实现并列效果
  • 刻度对齐优化:将x轴刻度放在对应月份所有柱子的中间位置,保证标签与柱子组精准对齐

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 23:30:33