Построить производную временного ряда со сглаженным видом в Python

У меня есть длинные временные ряды панд, как это:

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

Поскольку некоторые значения дельта-времени (то есть в denominat) очень близки (или иногда равны) нулю, я получил некоторые значения inf в моей производной. Практически я получил это:[1

Временной ряд синий (левая шкала), производный зеленый (правая шкала)

Теперь я хотел бы сгладить производную, чтобы сделать ее более читабельной. Я пробовал разные операции, такие как:

  • Рассчитать разницу по более высоким периодам:

установить периоды =5 как для числа, так и для деноминации

  • используйте скользящее среднее с: smotDeriv=derivative.rolling(window=10,min_periods=3,center=True,win_type='boxcar').mean() получение:

Я использовал также разные типы окон без каких-либо полезных изменений

  • Я думал также обрезать значения, но я не знаю, какие эффективные значения использовать как минимальные и максимальные. Я попробовал квантиль 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)

чтобы получить это:

Практически не могу найти полезного улучшения. Что вы можете предложить мне для улучшения читабельности производного графика на графике, если это возможно. Очевидно, я бы вырезал некоторый пик производной, чтобы получить сглаженную кривую, которая приближается к истинным значениям. Я пробовал разные комбинации типов окон, периодов и т. Д. Безрезультатно. Что касается фильтра Калмана, я не эксперт, скажем, новичок, поэтому я просто использовал значения по умолчанию после этого. Я также нашел библиотеку filterpy, которая реализует фильтр Калмана, но я не нашел, как использовать без установки начальных параметров.

2 ответа

Если ваша цель состоит в том, чтобы удалить "выбросы" всплесков в производных рядах, я бы сначала попробовал "скользящее среднее" вместо "скользящего среднего", поскольку медиана в целом более нечувствительна к выбросам.

Например:

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

И затем, если вы хотите еще больше сгладить его, одним из возможных вариантов является применение rolling_mean(),

Примечание. Поскольку у меня нет ваших данных для игры, я не уверен в оптимальных значениях для window а также min_periods, Это зависит от того, как далеко вы хотите сгладить его. Кроме того, мне кажется, что сглаживающая производная становится все более похожей на сглаживание исходного временного ряда, поэтому, если есть известный способ сглаживания исходного временного ряда, это может быть более простым.

Надеюсь это поможет.

Мы знаем, что производная функции определяется следующим образом:

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

Предположим, что производная вашей функции определяется везде, где. Когда h очень мало, вы получите лучшее приближение производной, а когда h очень большое, вы получите плохое приближение производной.

Существует проблема с применением этого подхода в случае вашего набора данных. Иногда h может стать очень маленьким, чтобы существенно увеличить абсурдное значение градиента. Иногда h слишком велико, чтобы оценка градиента была очень плохой. Чтобы преодолеть эту проблему, давайте определим два порога времени t1 и t2. Если последовательная разница во времени находится между t1 и t2, то мы используем эту точку для определения градиента по приведенной выше формуле f'(x). Если он находится за этим порогом, мы игнорируем этот момент.

Как мы вычисляем градиент для остальных точек?

Мы можем подогнать полином на основе точек, которые мы нашли на предыдущем шаге.

Другие вопросы по тегам