Pandas:计算事件周围时间序列数据的平均行为

Pandas: calculating average behaviour of time series data around an event

我有两个带有日期时间信息的数据框,df_stream 是事件流,df_events 是时间上的特定事件。例如:

蓝色是流,红色线是事件。 window 是 30min 事件的任一侧,时间粒度是 30s.

如何生成给定时间 window 和时间粒度内所有事件流的平均行为的数据帧/图表?

流数据帧如下所示:

                     streamEventId
DateTime                          
2020-08-20 10:39:24       44791313
2020-08-20 10:40:30       44791721
2020-08-20 10:40:54       44694121
2020-08-20 10:41:16       44902962
2020-08-20 10:42:04       44622569

事件数据框如下所示:

            DateTime
0 2020-11-17 09:49:00
1 2020-11-17 10:49:00
2 2020-11-17 11:11:00
3 2020-11-17 11:16:00
4 2020-11-17 12:11:00

我已经设法打印了每个事件的图表,并打印了各自的 windows,但我很难将逻辑结合起来。我也使用 iterrows,我不喜欢它。

我目前的做法:

for i in df_events[["DateTime"]].iterrows():
    date_time = i[1].values[0]
    before = date_time - pd.Timedelta(window)
    after = date_time + pd.Timedelta(window)

    df_stream_temp = df_stream.loc[before:after].copy()
    plt.figure(figsize=(20, 2))
    df_stream_mva = (
        df_stream.streamEventId.groupby(pd.Grouper(freq="30s"))
        .count()
        .loc[before:after]
    )

    y_height = df_stream_mva.max()

    ax = df_stream_mva.plot()
    plt.vlines(df_events.DateTime.to_list(), 0, y_height, color="lightcoral")
    ax.set_ylim([0, y_height]) 

这给出了一系列不错的图表:

等等...

我想计算并绘制上面的平均值和置信区间。

坐下来解决问题。

使用与我上面的 iterrows 示例类似的逻辑,我遍历了 df_events,创建了 beforeafter 时间 window 限制并使用了这些过滤按给定时间频率分组的 df_stream。然后使用时间增量索引重新计算索引以获得“与事件的距离”索引。然后将其附加到列表中,然后使用 pd.concat 和轴 1 组合。示例如下:

window = "30 min"
freq = "30s"

collect_list = []
for i in df_events[["DateTime"]].iterrows():
    date_time = i[1].values[0]
    before = date_time - pd.Timedelta(window)
    after = date_time + pd.Timedelta(window)

    df_stream_window = (
        df_stream.streamEventId.groupby(pd.Grouper(freq=freq))
        .count()
        .loc[before:after]
        .reset_index()
        .rename(columns={"streamEventId": "stream events"})
    )

    df_stream_window = df_stream_window.set_index(
        pd.to_timedelta((df_stream_window.DateTime - pd.to_datetime(date_time)))
        / np.timedelta64("1", "m")
    )

    collect_list.append(df_stream_window)

df_collect = pd.concat(collect_list, axis=1)

这生成了以下数据框:

                    DateTime  stream events            DateTime  \
DateTime                                                          
-30.0    2020-11-17 09:19:00              5 2020-11-17 10:19:00   
-29.5    2020-11-17 09:19:30              5 2020-11-17 10:19:30   
-29.0    2020-11-17 09:20:00              3 2020-11-17 10:20:00   
-28.5    2020-11-17 09:20:30              2 2020-11-17 10:20:30   
-28.0    2020-11-17 09:21:00              3 2020-11-17 10:21:00   

        stream events            DateTime  stream events  \
DateTime                                                     
-30.0                 3 2020-11-17 10:41:00              6   
-29.5                 5 2020-11-17 10:41:30              6   
-29.0                 3 2020-11-17 10:42:00              4   
-28.5                 3 2020-11-17 10:42:30              1   
-28.0                 1 2020-11-17 10:43:00              4   

....

然后可以在 Seaborn 中使用 estimator="mean" 绘图:

ax = sns.lineplot(data=df_collect, estimator="mean")
plt.axvline(0, color="lightcoral")
ax.set_xlabel("Time before / after event (min)")
ax.set_ylabel("# Stream Events")