Необходимо идентифицировать все идентификаторы, которые были созданы в окне +/- 10 минут с тем же идентификатором пользователя, используя pandas - PullRequest
0 голосов
/ 29 апреля 2020

Необходимо идентифицировать все идентификаторы, которые были созданы в окне +/- 10 минут с тем же идентификатором пользователя.

ID|user| Date              
--|----|-------------------         
1 |abc |2020-02-02 10:01:00
2 |abc |2020-02-02 10:09:00
3 |def |2020-02-02 10:17:00
4 |def |2020-02-02 11:00:00
5 |abc |2020-02-02 10:17:00

Желаемое o / p:

ID|user| Date              | CNT
--|----|-------------------|---         
1 |abc |2020-02-02 10:01:00|1
2 |abc |2020-02-02 10:09:00|2
3 |def |2020-02-02 10:17:00|1
4 |def |2020-02-02 11:00:00|0
5 |abc |2020-02-02 10:17:00|1

Я пытаюсь решить эту проблему с pandas. Пожалуйста, предоставьте некоторые данные о том, как этого можно достичь, объем данных будет go до 100 тыс. Записей.

Подход:

Я создал два столбца, как date_plus_10 и Date_minus_10. Затем я создал вложенный l oop, чтобы анализировать данные по одному и проверять, находится ли дата между date_plus_10 и Date_minus_10 и имеет ли тот же пользователь. Но это занимает много времени.

В приведенных ниже кодах 37 и 36 - это местоположение для date_plus_10 и Date_minus_10, 23 - это столбец даты, 15 - пользователь, а 38 - флаг / счетчик.

for i in range(0,100):
    time_range=DateTimeRange(data_rr_NAN.iloc[i,37],data_rr_NAN.iloc[i,36])
    for j in range(i+1,100):
        if (((data_rr_NAN.iloc[j,23] in time_range) == True) & (data_rr_NAN.iloc[j,15] == data_rr_NAN.iloc[i,15])):
            data_rr_NAN.iloc[i,38] += 1

1 Ответ

0 голосов
/ 29 апреля 2020

Я пробовал несколько вариантов использования операции .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, работа, выполняемая в каждой итерации, должна быть довольно быстрой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...