Python matplotlib绘图:仅含单日/部分日期数据时如何显示整月全日期x轴
问题定位
- 绘图入参长度不匹配:代码中
ax1.bar(dates,s)的两个参数来源不一致,dates是手动从业务表提取的去重后有记录的日期列表,s是resample按天聚合后的序列,二者长度存在偏差,直接导致绘图位置错位 - 数据源覆盖不全:手动提取的
dates仅包含存在业务记录的日期,完全没有纳入无数据的日期节点 - 未约束轴显示范围:没有主动指定横轴的上下边界,matplotlib会根据传入数据的最小、最大值自动收缩轴的显示区间,无法覆盖整月范围
调整方案
- 先确定需要展示的目标整月范围:从业务数据中提取所属月份(默认取数据中最新日期所在的自然月,可按需修改为指定年月),生成从当月1日到当月最后一天的完整日期区间,作为横轴的固定显示边界
- 统一绘图数据源:对日度聚合结果做缺失值补0处理——resample按天聚合时,所有有数据的日期会生成对应金额值,无数据的日期会保留索引、对应值为NaN,补0后这些日期的柱高为0,自然不会显示柱形。绘图时直接使用聚合序列的索引和值,不再使用手动去重的日期列表
- 强制固定横轴范围:通过
ax1.set_xlim将横轴的上下限绑定到整月的首日和末日,避免matplotlib自动收缩轴范围
调整后的可运行代码
import matplotlib.pyplot as plt import numpy as np import matplotlib.dates as mdates import datetime as dt import pandas as pd df=get_pandas_data(datab) # 统一将date列转为pandas日期格式,避免后续处理报错 df['date'] = pd.to_datetime(df['date']) fig = plt.figure(figsize=(10,10)) ax1 = fig.add_subplot(1,1,1) # ------------- 核心修改部分 ------------- # 1. 确定目标展示月份,默认取数据中最新日期所属的自然月 target_year = df['date'].dt.year.max() target_month = df['date'].dt.month.max() month_start = dt.date(target_year, target_month, 1) # 计算当月最后一天 if target_month == 12: next_month_first = dt.date(target_year + 1, 1, 1) else: next_month_first = dt.date(target_year, target_month + 1, 1) month_end = next_month_first - dt.timedelta(days=1) # 2. 日度聚合补0,缺失日期的金额记为0 daily_amount = df.resample('D', on='date')['amount'].sum().fillna(0) # 直接用聚合后的索引作为x轴值,无需手动提取去重日期 ax1.bar(daily_amount.index, daily_amount.values) # 3. 强制将横轴范围固定为整月首尾,确保全月日期都纳入显示 ax1.set_xlim(month_start, month_end) # ------------- 核心修改部分结束 ------------- ax1.set(xlabel="Date", ylabel="Balance (€)", title="Total Monthly balance") ax1.xaxis.set_major_formatter(mdates.DateFormatter('%d-%m-%Y')) ax1.xaxis.set_major_locator(mdates.DayLocator(interval=1)) fig.autofmt_xdate() plt.show()
调整后可实现的效果:
- 无业务数据的日期会完整出现在横轴刻度上,不会被自动跳过
- 仅在存在有效业务金额的日期位置绘制柱形,无数据日期的柱高为0,不会在图上显示多余图形
- 配合
DayLocator(interval=1)的刻度规则,会逐天展示全月的日期标签
内容的提问来源于stack exchange,提问作者EfrenPy
相关产品推荐
相关产品推荐

