Как назначить уникальный идентификатор для разных групп в панде dataframe? - PullRequest
2 голосов
/ 10 июля 2019

Как назначить уникальные идентификаторы группам, созданным в кадре данных pandas на основе определенных условий. Например: у меня есть фрейм данных с именем df со следующей структурой: Name идентифицирует пользователя, а datetime идентифицирует дату / время, когда пользователь обращается к ресурсу.

Name         Datetime 
Bob          26-04-2018 12:00:00 
Claire       26-04-2018 12:00:00 
Bob          26-04-2018 12:10:00 
Bob          26-04-2018 12:30:00 
Grace        27-04-2018 08:30:00 
Bob          27-04-2018 09:30:00 
Bob          27-04-2018 09:40:00 
Bob          27-04-2018 10:00:00 
Bob          27-04-2018 10:30:00 
Bob          27-04-2018 11:30:00

Я хотел бы создать сеансы для пользователей таким образом, чтобы пользователям с одинаковыми значениями имени и даты и времени, обращающимися к ресурсу не более 30 минут, был назначен уникальный сеанс. Однако, если пользователь демонстрирует некоторую неактивность в течение более 30 минут при доступе к ресурсу, тому же пользователю будет назначен другой сеанс для следующего доступа пользователя к ресурсу.

Мой ожидаемый результат будет таким, как показано.

Пользователь Боб 27-04-2018, получил доступ к ресурсу в 9.30, во второй раз @ 9.40, в третий раз @ 10.00, в четвертый раз @ 10.30 -> все с сеансом 4. Но в следующий раз пользователь Боб получит доступ @ 11.30, поэтому разница во времени превышает 30 минут, поскольку Боб неактивен более 30 минут, поэтому ему будет назначена следующая сессия.

Name         Datetime                    Id
Bob          26-04-2018 12:00:00          1
Claire       26-04-2018 12:00:00          2
Bob          26-04-2018 12:10:00          1
Bob          26-04-2018 12:30:00          1
Grace        27-04-2018 08:30:00          3
Bob          27-04-2018 09:30:00          4
Bob          27-04-2018 09:40:00          4
Bob          27-04-2018 10:00:00          4
Bob          27-04-2018 10:30:00          4
Bob          27-04-2018 11:30:00          5

Спасибо за вашу помощь! Ссылка на предыдущий вопрос: Как сравнить значение второго столбца с такими же значениями первого столбца в кадре данных панд?

Ответы [ 2 ]

2 голосов
/ 10 июля 2019

sort и найдите разницу во времени ('td') для последовательных действий.cumsum логическая серия для формирования групп последовательных действий в течение 30 минут после последней.ngroup помечает группы.

Можно удалить sort_index перед groupby, если вам все равно, какую метку получают группы, но это гарантирует, что они упорядочены на основе исходного порядка.

df = df.sort_values(['Name', 'Datetime'])
df['td'] = df.Datetime.diff().mask(df.Name.ne(df.Name.shift()))
                             # Only calculate diff within same Name
df['Id'] = (df.sort_index()
              .groupby(['Name', df['td'].gt(pd.Timedelta('30min')).cumsum()], sort=False)
              .ngroup()+1)
df = df.sort_index()

Вывод:

td оставлено для ясности

     Name            Datetime       td  Id
0     Bob 2018-04-26 12:00:00      NaT   1
1  Claire 2018-04-26 12:00:00      NaT   2
2     Bob 2018-04-26 12:10:00 00:10:00   1
3     Bob 2018-04-26 12:30:00 00:20:00   1
4   Grace 2018-04-27 08:30:00      NaT   3
5     Bob 2018-04-27 09:30:00 21:00:00   4
6     Bob 2018-04-27 09:40:00 00:10:00   4
7     Bob 2018-04-27 10:00:00 00:20:00   4
8     Bob 2018-04-27 10:30:00 00:30:00   4
9     Bob 2018-04-27 11:30:00 01:00:00   5
1 голос
/ 11 июля 2019

Ваше объяснение внизу очень полезно для понимания.

Вам нужно сгруппироваться по Name и groupID (не путайте это groupID с вашим окончательным Id) и позвоните ngroup, чтобы вернуть Id. Главное, как это определить groupID. Чтобы создать groupID, вам нужно sort_values, чтобы разделить каждые Name и Datetime в порядке возрастания. Сгруппируйте Name и найдите различия в Datetime между последовательными строками в каждой группе Name (в том же Name). Использование gt для проверки более 30 минут и cumsum для получения groupID. sort_index, чтобы вернуться к исходному порядку и присвоить s следующим образом:

s = df.sort_values(['Name','Datetime']).groupby('Name').Datetime.diff() \
      .gt(pd.Timedelta(minutes=30)).cumsum().sort_index()

Далее, groupby Name и s с sort=False, чтобы зарезервировать исходный заказ, и набрать ngroup plus 1.

df['Id'] = df.groupby(['Name', s], sort=False).ngroup().add(1)

Out[834]:
     Name            Datetime  Id
0     Bob 2018-04-26 12:00:00   1
1  Claire 2018-04-26 12:00:00   2
2     Bob 2018-04-26 12:10:00   1
3     Bob 2018-04-26 12:30:00   1
4   Grace 2018-04-27 08:30:00   3
5     Bob 2018-04-27 09:30:00   4
6     Bob 2018-04-27 09:40:00   4
7     Bob 2018-04-27 10:00:00   4
8     Bob 2018-04-27 10:30:00   4
9     Bob 2018-04-27 11:30:00   5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...