Постройте производную временного ряда со сглаженным видом в 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

Поскольку некоторые значения дельта-времени (то есть в номинальном выражении) очень близки (или иногда равны) нулю, я получил некоторые значения 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, которая реализует фильтр Калмана, но я не нашел, как использовать ее без установки начальных параметров.


person SPS    schedule 08.06.2018    source источник


Ответы (2)


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

Например:

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

А потом, если хотите еще сгладить, один из возможных вариантов - применить rolling_mean().

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

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

person gyoza    schedule 14.06.2018

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

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

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

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

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

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

person Abhishek Mishra    schedule 15.06.2018