Pandas 滚动时间 window 多列自定义函数

Pandas rolling time window custom functions with multiple columns

我在 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

我正在尝试计算 tpdevice_tp 之间的皮尔逊相关系数,并使用滚动时间 window 对每个数据应用动态时间扭曲算法(使用 fastdtw) .对于每个样本,我回顾过去 12 小时并计算相关系数和距离。

我知道 pandas 作为滚动函数,但是,它不是 return 数据框而是一个系列(或数组?)。问题是相关因子和 fastdtw 都需要两个参数才能工作:df.tpdf.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 内置函数的内容,但真的看不出如何做到这一点。

感谢您的帮助!

好的,所以获得窗口相关性的有效方法是 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)

但是这个解决方案也不太好。假定数据点之间的距离恒定为 1h(以便使用索引)。如果不是这种情况,则需要对其进行调整。