如何同图绘制不同起始日期时间序列并解决x轴标签重叠问题
Matplotlib时间序列绘图问题修复方案
绘图前先做基础格式预处理,确保所有数据集的日期列被正确识别为时间类型:
import pandas as pd import matplotlib.pyplot as plt import matplotlib.dates as mdates # 若使用插值平滑方案,额外导入以下依赖 from scipy.interpolate import make_interp_spline import numpy as np # 统一将Date列转为datetime格式 for df in [df_all, df_t, df_c]: df['Date'] = pd.to_datetime(df['Date'])
一、x轴日期重叠问题解决
通过自定义日期刻度规则、调整标签布局彻底解决重叠:
- 绘图时显式指定x、y参数,不要直接传入整个DataFrame,避免matplotlib解析列出错
- 用
matplotlib.dates内置的刻度定位器设置刻度密度,针对1年2个月的时间跨度,设置每月1个主刻度即可,不会过密 - 统一日期显示格式为
年-月,将标签旋转45度右对齐,同时调用自动布局方法防止标签被画布截断 - 显式指定x轴范围,起点为2020-03-01,终点为三个数据集共有的截止日期2021-05-31
二、折线平滑方案
两种常用方案按需选择:
- 滑动窗口平均平滑:无额外依赖,对原始数据做滚动窗口均值计算,最大程度保留真实数据趋势,不会出现偏离真实值的问题,适合业务分析场景。日度数据选择7/14天窗口即可,平衡平滑度和真实性。
- 三次样条插值平滑:曲线顺滑度更高,通过对原始离散点做多项式插值,生成更密集的采样点后连线,适合展示类场景。注意不要设置过高的采样点数,避免曲线过度扭曲偏离原始数据。
完整参考代码
代码中包含三种绘图模式,注释掉不需要的部分即可使用:
fig, ax = plt.subplots(figsize=(12, 6)) # -------------------------- # 模式1:原始折线(仅修复x轴问题) # -------------------------- # ax.plot(df_all['Date'], df_all['Quantity A'], color='tab:red', label='Quantity A') # ax.plot(df_t['Date'], df_t['Quantity B'], color='tab:blue', label='Quantity B') # ax.plot(df_c['Date'], df_c['Quantity C'], color='tab:green', label='Quantity C') # -------------------------- # 模式2:7天滑动窗口平滑 # -------------------------- # df_all['smooth_A'] = df_all['Quantity A'].rolling(window=7, center=True).mean() # df_t['smooth_B'] = df_t['Quantity B'].rolling(window=7, center=True).mean() # df_c['smooth_C'] = df_c['Quantity C'].rolling(window=7, center=True).mean() # ax.plot(df_all['Date'], df_all['smooth_A'], color='tab:red', label='Quantity A') # ax.plot(df_t['Date'], df_t['smooth_B'], color='tab:blue', label='Quantity B') # ax.plot(df_c['Date'], df_c['smooth_C'], color='tab:green', label='Quantity C') # -------------------------- # 模式3:三次样条插值平滑 # -------------------------- def calc_smooth_curve(x, y, sample_points=300): x_num = mdates.date2num(x) spline = make_interp_spline(x_num, y, k=3) x_smooth_num = np.linspace(x_num.min(), x_num.max(), sample_points) y_smooth = spline(x_smooth_num) x_smooth = mdates.num2date(x_smooth_num) return x_smooth, y_smooth x_a, y_a = calc_smooth_curve(df_all['Date'], df_all['Quantity A']) x_b, y_b = calc_smooth_curve(df_t['Date'], df_t['Quantity B']) x_c, y_c = calc_smooth_curve(df_c['Date'], df_c['Quantity C']) ax.plot(x_a, y_a, color='tab:red', label='Quantity A') ax.plot(x_b, y_b, color='tab:blue', label='Quantity B') ax.plot(x_c, y_c, color='tab:green', label='Quantity C') # x轴配置 ax.xaxis.set_major_locator(mdates.MonthLocator(interval=1)) ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m')) ax.set_xlim(pd.to_datetime('2020-03-01'), pd.to_datetime('2021-05-31')) plt.xticks(rotation=45, ha='right') fig.autofmt_xdate() # 基础图表配置 ax.set_xlabel('Date') ax.set_ylabel('Quantity') ax.legend() plt.tight_layout() plt.show()
注意事项:使用插值平滑前需要先删除对应列的空值,否则会触发计算错误;滑动窗口计算后,序列首尾会存在长度为窗口1/2的空值,属于正常现象。
内容的提问来源于stack exchange,提问作者RafaelP
相关产品推荐
相关产品推荐

