Я пробовал несколько вариантов использования операции .rolling()
с размером окна, основанным на времени, но, похоже, у него есть ряд ограничений, которые затрудняют использование для этого варианта использования.
Вот простой подход, который перебирает DataFrame и находит строки, попадающие в окно. Я подозреваю, что есть гораздо более эффективный способ сделать это, но он может быть достаточно быстрым для вашей ситуации.
import numpy as np
import pandas as pd
create_user_log = np.array(
[[1, pd.Timestamp('20200202 10:01:00'), 'abc'],
[2, pd.Timestamp('20200202 10:09:00'), 'abc'],
[3, pd.Timestamp('20200202 10:17:00'), 'def'],
[4, pd.Timestamp('20200202 11:00:00'), 'def'],
[5, pd.Timestamp('20200202 10:17:00'), 'abc'],
[6, pd.Timestamp('20200202 11:09:00'), 'abc'],
[7, pd.Timestamp('20200202 11:56:00'), 'def'],
[8, pd.Timestamp('20200202 12:00:00'), 'def'],
[9, pd.Timestamp('20200202 12:05:00'), 'abc'],
])
df = pd.DataFrame(data=create_user_log, columns=["id", "date", "user"])
df.set_index('date', inplace=True)
df.sort_index(inplace=True)
counts = []
for row in df.itertuples(index=True, name='Pandas'):
win = df[(row[0] - pd.DateOffset(minutes=10)):(row[0] + pd.DateOffset(minutes=10))]
counts.append(len(win[win['user']==row.user]))
df['cnt'] = counts
display(df)
Вывод:
id user cnt
date
2020-02-02 10:01:00 1 abc 2
2020-02-02 10:09:00 2 abc 3
2020-02-02 10:17:00 3 def 1
2020-02-02 10:17:00 5 abc 2
2020-02-02 11:00:00 4 def 1
2020-02-02 11:09:00 6 abc 1
2020-02-02 11:56:00 7 def 2
2020-02-02 12:00:00 8 def 2
2020-02-02 12:05:00 9 abc 1
Я не фанат используя itertuples()
, но поскольку мы проиндексировали date
, работа, выполняемая в каждой итерации, должна быть довольно быстрой.