如何移除Pandas折线图中的空白日期并平滑图表
移除时间序列折线图的无关日期并平滑图表
要解决这个问题,你可以分两步处理:先移除无关日期间隔,再平滑图表。
一、移除无关日期间隔
当时间序列数据存在非连续日期时,pandas默认会自动补全日期间隔,导致x轴出现空白。要避免这种情况,你可以用以下两种方法:
方法1:把日期当作离散分类变量绘图
直接将日期转为字符串格式作为x轴,让matplotlib把每个日期视为独立的分类项,不会自动补全间隔:
import matplotlib.pyplot as plt import pandas as pd # 示例数据 data = { 'date': ['2024-01-01', '2024-01-03', '2024-01-05', '2024-01-10', '2024-01-20'], 'value': [10, 15, 12, 20, 18] } df = pd.DataFrame(data) df['date'] = pd.to_datetime(df['date']) plt.figure(figsize=(10, 6)) # 将日期转为字符串格式,避免自动补全间隔 plt.plot(df['date'].dt.strftime('%Y-%m-%d'), df['value'], marker='o') plt.xticks(rotation=45) plt.xlabel('日期') plt.ylabel('数值') plt.title('无间隔日期折线图') plt.tight_layout() plt.show()
方法2:手动指定x轴刻度
如果想保留datetime类型的日期,你可以强制x轴只显示数据中存在的日期:
plt.figure(figsize=(10, 6)) plt.plot(df['date'], df['value'], marker='o') # 手动设置x轴刻度为数据中的日期,并格式化显示 plt.xticks(df['date'], df['date'].dt.strftime('%Y-%m-%d'), rotation=45) plt.xlabel('日期') plt.ylabel('数值') plt.title('无间隔日期折线图') plt.tight_layout() plt.show()
注意:x_compat=True参数只是让pandas的日期绘图兼容matplotlib的日期格式,不会移除缺失的日期间隔,所以对你的问题没用。
二、平滑折线图
如果需要让折线更平滑,可以用以下两种常用方法:
方法1:移动平均平滑
通过滚动窗口计算移动平均,简单易操作,适合弱化短期波动:
# 计算2期移动平均(可根据需求调整window大小) df['smoothed_value'] = df['value'].rolling(window=2, min_periods=1).mean() plt.figure(figsize=(10, 6)) plt.plot(df['date'].dt.strftime('%Y-%m-%d'), df['value'], marker='o', label='原始数据') plt.plot(df['date'].dt.strftime('%Y-%m-%d'), df['smoothed_value'], marker='s', label='平滑后数据') plt.xticks(rotation=45) plt.xlabel('日期') plt.ylabel('数值') plt.title('移动平均平滑折线图') plt.legend() plt.tight_layout() plt.show()
方法2:样条插值平滑
用scipy的样条插值生成连续平滑的曲线,适合需要更流畅视觉效果的场景:
from scipy.interpolate import make_interp_spline import numpy as np # 将日期转换为数值索引以便插值 x_num = np.arange(len(df['date'])) # 生成50个平滑后的点(可调整数量控制平滑程度) y_smooth = make_interp_spline(x_num, df['value'])(np.linspace(x_num.min(), x_num.max(), 50)) plt.figure(figsize=(10, 6)) plt.plot(df['date'].dt.strftime('%Y-%m-%d'), df['value'], marker='o', label='原始数据') # 生成对应数量的日期标签 smooth_dates = pd.date_range(df['date'].min(), df['date'].max(), periods=50).strftime('%Y-%m-%d') plt.plot(smooth_dates, y_smooth, label='平滑后数据') plt.xticks(rotation=45) plt.xlabel('日期') plt.ylabel('数值') plt.title('样条插值平滑折线图') plt.legend() plt.tight_layout() plt.show()
内容的提问来源于stack exchange,提问作者Vel Kumar
相关产品推荐
相关产品推荐

