熊猫 - 滚动窗口 - 不均匀间隔

tom*_*ler 6 python time-series pandas

我在解决此数据集中适用于每个买家的滚动交易数量时遇到问题,结构如下:

userID  itemID      transaction_ts
3229    4493320     2016-01-02 14:55:00
3229    4492492     2016-01-02 14:57:02
3229    4496756     2016-01-04 09:01:18
3229    4493673     2016-01-04 09:11:10
3229    4497531     2016-01-04 11:05:25
3229    4495006     2016-01-05 07:25:11
4330    4500695     2016-01-02 09:17:21
4330    4500656     2016-01-03 09:19:28
4330    4503087     2016-01-04 07:42:15
4330    4501846     2016-01-04 08:55:24
4330    4504105     2016-01-04 09:59:35
Run Code Online (Sandbox Code Playgroud)

理想情况下,对于例如24小时的滚动事务计数窗口,它看起来如下所示:

userID  itemID      transaction_ts        rolling_count
3229    4493320     2016-01-02 14:55:00         1
3229    4492492     2016-01-02 14:57:02         2
3229    4496756     2016-01-04 09:01:18         1
3229    4493673     2016-01-04 09:11:10         2
3229    4497531     2016-01-04 11:05:25         3
3229    4495006     2016-01-05 07:25:11         4
4330    4500695     2016-01-02 09:17:21         1
4330    4500656     2016-01-03 09:19:28         1
4330    4503087     2016-01-04 07:42:15         2 
4330    4501846     2016-01-04 08:55:24         3
4330    4504105     2016-01-04 09:59:35         3
Run Code Online (Sandbox Code Playgroud)

这里有类似问题的优秀答案:熊猫滚动最后五分钟的总和

但是,这个答案完全取决于时间戳字段,与上面的情况不同,滚动计数在遇到从不同用户到上一行的事务时必须重置为1.可以通过切片找到解决方案,但是给定该数据集的大小(可能是1m +行)是不可行的.

至关重要的是,窗口应该反映相应行的transactional_ts之前的24小时时段,因此为什么我认为自定义df.apply或rolling_window方法是合适的,我只是无法弄清楚如何在userID上进行条件限制.

ptr*_*trj 4

解决方案的一部分(滚动累积和)可能已经在这里。(我只改变了滞后的类型):

from datetime import timedelta

def msum(s, lag):
    lag = s.index - timedelta(days=lag)
    inds = np.searchsorted(s.index.astype(np.int64), lag.astype(np.int64))
    cs = s.cumsum()
    return pd.Series(cs.values - cs[inds].values + s[inds].values, index=s.index)
Run Code Online (Sandbox Code Playgroud)

该函数要求索引为日期时间类型。此外,每个 userID 组内的索引应该已经排序(例如,如您的示例中所示)。

df = df.set_index('transaction_ts')
df['rolling_count'] = 1
df['rolling_count'] = df.groupby('userID', sort=False)['rolling_count'].transform(lambda x : msum(x,1))
Run Code Online (Sandbox Code Playgroud)

groupby 选项sort=False可能会提高一些速度。(它负责对组键进行排序。)