Группировка данных Pandas

Есть датасет логов действий пользователей:

id,
сессия,
браузер,
действие

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

Как это можно сделать? Я так понимаю нужно использовать groupby(), но немного не понимаю механизм реализации такого запроса. По примерах тяжело сделать то что мне нужно в силу моего опыта.

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


Ответы (1 шт):

Автор решения: strawdog

В общем случае, вы всегда можете "разрезать" датафрейм по определенному значению, а затем сделать группировку:

import pandas as pd
df = pd.DataFrame({"events":["e1", "e2", "approved", "e2", "e4", "e7", "approved", "e42"]})
     events
0        e1
1        e2
2  approved
3        e2
4        e4
5        e7
6  approved
7       e42
df["grp"] = df["events"].eq("approved").cumsum().shift().bfill()
     events  grp
0        e1  0.0
1        e2  0.0
2  approved  0.0
3        e2  1.0
4        e4  1.0
5        e7  1.0
6  approved  1.0
7       e42  2.0
res = df.groupby("grp")["events"].apply(list)
print(res)
grp
0.0        [e1, e2, approved]
1.0    [e2, e4, e7, approved]
2.0                     [e42]
Name: events, dtype: object

UPDATE:

import pandas as pd
df = pd.DataFrame({"events":["e1", "e2", "approved", "e2", "e4", "e7", "approved", "e42"],
                   "users":["user1", "user2", "user2", "user1", "user1", "user2", "user1", "user2"]})
     events  users
0        e1  user1
1        e2  user2
2  approved  user2
3        e2  user1
4        e4  user1
5        e7  user2
6  approved  user1
7       e42  user2
res = []
for i, g in  df.groupby("users")[["events", "users"]]:
    g["grp"] = g["events"].eq("approved").cumsum().shift().bfill()
    res.append(({i:g.groupby("grp")["events"].apply(list).values.tolist()}))
print(res)
[{'user1': [['e1', 'e2', 'e4', 'approved']]}, {'user2': [['e2', 'approved'], ['e7', 'e42']]}]

UPDATE 2

import pandas as pd
df = pd.DataFrame({"events":["e1", "e2", "approved", "e2", "e4", "e7", "approved", "e42"],
                   "users":["user1", "user2", "user2", "user1", "user1", "user2", "user1", "user2"],
                   "attr1": [1, 2, 3, 4, 5, 6, 7, 8],
                   "attr2": [11, 22, 33, 44, 55, 66, 77, 88]
                  })
     events  users  attr1  attr2
0        e1  user1      1     11
1        e2  user2      2     22
2  approved  user2      3     33
3        e2  user1      4     44
4        e4  user1      5     55
5        e7  user2      6     66
6  approved  user1      7     77
7       e42  user2      8     88
res = pd.DataFrame()
for i, g in  df.groupby("users", as_index=False):
    g["grp"] = g["events"].eq("approved").cumsum().shift().bfill()
    res = pd.concat([res, g.groupby("grp")[["events", "attr1", "attr2", "users"]]
                     .agg({"events": list, "attr1":list, "attr2":list, "users":lambda x: list(x)[0]} )])
print(res)
                     events         attr1             attr2  users
grp                                                               
0.0  [e1, e2, e4, approved]  [1, 4, 5, 7]  [11, 44, 55, 77]  user1
0.0          [e2, approved]        [2, 3]          [22, 33]  user2
1.0               [e7, e42]        [6, 8]          [66, 88]  user2
→ Ссылка