在Python中绘制具有平滑外观的时间序列的导数

时间:2018-06-08 17:52:40

标签: python pandas kalman-filter pykalman

我有一个像这样的长熊猫时间序列:

2017-11-27 16:19:00     120.0
2017-11-30 02:40:35     373.4
2017-11-30 02:40:42     624.5
2017-12-01 14:15:31     871.8
2017-12-01 14:15:33    1120.0
2017-12-07 21:07:04    1372.2
2017-12-08 06:11:50    1660.0
2017-12-08 06:11:53    1946.7
2017-12-08 06:11:57    2235.3
2017-12-08 06:12:00    2521.3
....
dtype: float64

我希望将它与其衍生物一起绘制。根据定义,我以这种方式计算导数:

numer=myTimeSeries.diff()
denominat=myTimeSeries.index.to_series().diff().dt.total_seconds()/3600
derivative=numer/denominat

因为delta时间的某些值(以denominat为单位)非常接近(或有时相等)为零,所以我的导数中得到了一些inf值。实际上我得到了这个:[]. [1]

时间序列蓝色(左侧刻度),衍生绿色(右侧刻度)

现在我想平滑衍生物以使其更具可读性。我尝试了不同的操作,例如:

  • 计算更高期间的差异: enter image description here

为numer和denominat设置句点= 5

  • 使用移动平均线:smotDeriv=derivative.rolling(window=10,min_periods=3,center=True,win_type='boxcar').mean()获取:

enter image description here

我还使用了不同的窗口类型而没有任何有用的更改

  • 我还想削减这些值,但我不知道哪些有效值可以用作min和max。我尝试了25%和75%的分位数没有任何好处
  • 我还使用pykalman使用卡尔曼滤波器:

    derivative.fillna(0,inplace=True) kf = KalmanFilter(initial_state_mean=0) state_means,_ = kf.filter(derivative.values) state_means = state_means.flatten() indexDate=derivative.index derivativeKalman=pd.Series(state_means,index=indexDate)

得到这个:

enter image description here

实际上我找不到任何有用的改进。如果有可能,你能建议我如何提高图表上衍生图的可读性。显然,我会削减导数的某个峰值,以获得接近真实值的平滑曲线。我尝试了关于窗口类型,周期等的不同组合..没有任何结果。关于卡尔曼滤波器,我不是专家,让我们说一个新手,所以我只使用了this之后的默认值。我也找到了实现卡尔曼滤波器的filterpy库,但是我没有找到如何在不设置启动参数的情况下使用它。

2 个答案:

答案 0 :(得分:1)

如果您的目标是消除衍生系列中的“异常值”峰值,我会首先尝试“滚动中位数”而不是“滚动均值”,因为中位数通常对异常值更不敏感。

例如:

smotDeriv = derivative.rolling(window=10, min_periods=3, center=True).median()

然后,如果您想进一步解决这个问题,可能的选择之一就是应用rolling_mean()

注意:由于我手边没有您的数据,我不确定windowmin_periods的最佳值。这取决于你想要平滑多远。此外,在我看来,平滑导数变得更像平滑原始时间序列,所以如果有一种已知的方法来平滑原始时间序列,那可能更直接。

希望这有帮助。

答案 1 :(得分:0)

我们知道函数的派生定义如下:

  

f'(x)= lim_(h - > 0)(f(x + h) - f(x - h))/ 2h

让我们假设你的函数的导数是在每个地方定义的。当h非常小时,你会得到一个更好的导数近似值,当h非常大时,你会得到一个很差的导数近似值。

在数据集的情况下应用此方法存在问题。有时h可能变得非常小,基本上给出了非常高的梯度值。有时h太大,梯度估计非常糟糕。为了克服这个问题,我们定义两个时间阈值t1和t2。如果连续时间差在t1和t2之间,那么我们使用该点通过上述f'(x)公式确定梯度。如果超出此阈值,我们会忽略这一点。

  

我们如何计算其余点的渐变?

我们可以根据我们在上一步中找到的点拟合多项式。