Пользовательские функции скользящего временного окна 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)
Но, конечно, это действительно не время эффективно! Также мне интересно, что было бы лучшим способом сделать это? Я прочитал кое-что о переопределении функции прокрутки вместо использования встроенной функции панд, но не могу понять, как это сделать.
Спасибо за помощь!
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 час (для использования индексов). Вам нужно будет настроить его, если это не так.