Пользовательские функции окна скользящего времени Pandas с несколькими столбцами

У меня есть данные таймсерий в pandas DataFrame, которые выглядят так:

ts                         serial_number    device_tp       tp
2017-09-19T15:00:00.000Z    4ktpjlv     21.7760333333333    17
2017-09-19T14:00:00.000Z    4ktpjlv     19.8849833333333    16
2017-09-19T13:00:00.000Z    4ktpjlv     18.8565818181818    15
2017-09-19T12:00:00.000Z    4ktpjlv     18.7219666666667    13
2017-09-19T11:00:00.000Z    4ktpjlv     18.8341272727273    13
2017-09-19T10:00:00.000Z    4ktpjlv     18.9697833333333    14
2017-09-19T09:00:00.000Z    4ktpjlv     19.0422416666667    14

Я пытаюсь вычислить коэффициент корреляции Пирсона между tp и device_tp и применить алгоритм динамического искажения времени (с использованием fastdtw) к каждому данным, используя скользящее временное окно. Для каждого образца я оглядываюсь на последние 12 часов и вычисляю коэффициент корреляции и расстояние.

Я знаю, что pandas является скользящей функцией, однако она возвращает не фрейм данных, а серию (или массив?). Проблема в том, что и коэффициенту корреляции, и fastdtw для работы нужны два аргумента: df.tp и df.device_tp.

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

for key, meas in df.iterrows(): 
   now = meas.ts
   start_date = now - pd.Timedelta(hours=12)
   new_df = df[(df['ts'] >= start_date) & (df['ts'] < now)]   
   if(new_df.shape[0] > 1):
       tp = df.tp.values
       device_tp = df.device_tp.values
       distance, _ = fastdtw(df['tp'], df['device_tp'])
       corr = stats.pearsonr(tp, device_tp)[0]
       # ... Predict flag here
       if(flag == 0):
           output = output.append(meas)

Но, конечно, это действительно неэффективно по времени! Также мне интересно, что было бы лучше сделать это? Я читал кое-что о переопределении функции прокрутки вместо использования встроенной функции pandas, но не понимаю, как это сделать.

Спасибо за помощь !


person JiLan    schedule 17.12.2018    source источник
comment
Я не слишком знаком с этой темой, но помогает ли df["device_tp"].rolling(12, min_periods=2).corr(other=df["tp"]) в части корреляции?   -  person SamProell    schedule 17.12.2018
comment
@SamProell Да, это работает для корреляции, спасибо. Все еще борется за другую функцию   -  person JiLan    schedule 18.12.2018


Ответы (1)


Хорошо, поэтому эффективный способ получить оконную корреляцию - df["device_tp"].rolling(12, min_periods=2).corr(other=df["tp"]).

Я также не могу придумать простой способ получить расстояние DTW. Одно из решений, которое дает мне примерно 8-кратное ускорение, - это пролистать pd.Series индексов и использовать полученные индексы с Rolling.apply:

from fastdtw import fastdtw 
def rolling_dtw(df, win=12, center=False, min_periods=2,
                col0="ts", col1="A", col2="B"):
    indices = df[col0]
    a = df[col1].values
    b = df[col2].values
    def rolldist(inds):  # calculate DTW for current indices
        inds = inds.astype(int)  # manual type-cast is needed here
        return fastdtw(a[inds], b[inds])[0]

    return indices.rolling(win, center=center,
                           min_periods=min_periods).apply(rolldist)

Но это решение тоже не очень красивое. Предполагается, что расстояния между точками данных постоянны в 1 час (для использования индексов). Если это не так, вам необходимо отрегулировать его.

person SamProell    schedule 19.12.2018
comment
Спасибо за эту помощь, мне просто пришлось изменить способ создания индексов на: indices = pd.Series(range(0,df.shape[0])). В остальном работает нормально. Я также использую такую ​​же функцию для вычисления скользящей корреляции. Если я использую сборку в Pandas rolling.corr, у меня есть некоторые значения NaN, которых нет в SciPy. Не удалось найти причину ... - person JiLan; 25.12.2018