如何平滑Matplotlib折线图?海量日期离散数据需绘制趋势线
如何将日期离散数据绘制成平滑趋势线?
嘿,我太懂你现在的烦恼了——直接用pandas画出来的离散折线确实看起来乱糟糟的,完全体现不出趋势!要做出平滑的趋势线,其实有两种非常实用的方法,我给你一步步讲清楚:
方法一:插值法生成贴合数据的平滑曲线
这种方法会在原始数据点之间生成连续的插值点,让折线变得丝滑,而且能很好贴合原始数据。关键是要先把日期索引转成真正的datetime类型,不然pandas没法正确处理时间序列:
import pandas as pd import matplotlib.pyplot as plt import matplotlib matplotlib.style.use('ggplot') # 你的原始日期数据 matr = {'2017-03-01':20,'2017-03-02':1,'2017-03-03':50} # 第一步:把字符串索引转成datetime类型,这是核心前提! p = pd.Series(data=matr.values(), index=pd.to_datetime(matr.keys())) # 第二步:重采样到更细的时间粒度(比如每小时),再用三次样条插值填充 # 你也可以试试其他插值方法:linear(线性)、quadratic(二次样条) p_smooth = p.resample('H').interpolate(method='spline', order=3) # 第三步:绘图,同时保留原始数据点做参考 plt.figure(figsize=(14,10)) # 画平滑趋势线 p_smooth.plot(label='平滑趋势线', marker=None, linewidth=2) # 画原始数据点(用散点更清晰) p.plot(label='原始数据点', marker='o', linestyle='None', color='red') plt.grid(True) plt.xticks(rotation=0) plt.xlabel('Date') plt.ylabel('Value') plt.legend() plt.show()
方法二:多项式拟合得到整体趋势线
如果你的需求是看整体趋势,不需要完全贴合每个数据点(比如个别点是异常值),那多项式拟合就更合适:
import pandas as pd import matplotlib.pyplot as plt import matplotlib import numpy as np matplotlib.style.use('ggplot') matr = {'2017-03-01':20,'2017-03-02':1,'2017-03-03':50} p = pd.Series(data=matr.values(), index=pd.to_datetime(matr.keys())) # 把日期转成连续数值(比如距离第一个日期的天数),方便拟合计算 x = np.arange(len(p)) y = p.values # 用三次多项式拟合,degree可以调整(比如2是二次拟合) # 注意:degree不要超过数据点数量-1,避免过拟合 z = np.polyfit(x, y, 3) p_fit = np.poly1d(z) # 生成更多的连续x点,让拟合线更平滑 x_smooth = np.linspace(x.min(), x.max(), 100) y_smooth = p_fit(x_smooth) # 绘图 plt.figure(figsize=(14,10)) # 把数值x转回日期索引,保证横轴正确显示 plt.plot(p.index[x_smooth.astype(int)], y_smooth, label='拟合趋势线', linewidth=2) # 原始数据点用散点展示 plt.scatter(p.index, y, label='原始数据点', color='red') plt.grid(True) plt.xticks(rotation=0) plt.xlabel('Date') plt.ylabel('Value') plt.legend() plt.show()
小提示
- 不管用哪种方法,一定要把索引转成datetime类型,不然时间轴的处理会出问题
- 插值法里,
spline的平滑效果最好,适合需要贴合数据的场景;linear是线性插值,会生成更紧凑的折线 - 多项式拟合的
degree别设太高,比如你只有3个数据点,最多用3次多项式,数据量多的话用2-3次就足够,避免过拟合
内容的提问来源于stack exchange,提问作者NCNecros
相关产品推荐
相关产品推荐

