#python #python-3.x #pandas #dataframe
Вопрос:
У меня есть журнал приложений, который я помещаю в фрейм данных pandas, разбирая различные фрагменты каждого события на отдельные столбцы, что похоже на это:
data1 = {'timestamp': ['01-01-2021 12:00:00','01-01-2021 12:01:00','01-01-2021 12:02:00','01-01-2021 12:03:00','01-01-2021 12:04:00','01-01-2021 12:05:00','01-01-2021 12:06:00','01-01-2021 12:07:00','01-01-2021 12:08:00','01-01-2021 12:09:00','01-01-2021 12:10:00','01-01-2021 12:11:00','01-01-2021 12:12:00','01-01-2021 12:13:00','01-01-2021 12:14:00'],
'event': ['start','x','y','start','z','end','x','end','start','x','end','start','q','end','start'],
'account': ['bob','bob','bob','jane','bob','bob','jane','jane','todd','todd','todd','bob','bob','bob','ned'] }
df1 = pd.DataFrame(data1)
print(df1)
timestamp event account
0 01-01-2021 12:00:00 start bob
1 01-01-2021 12:01:00 x bob
2 01-01-2021 12:02:00 y bob
3 01-01-2021 12:03:00 start jane
4 01-01-2021 12:04:00 z bob
5 01-01-2021 12:05:00 end bob
6 01-01-2021 12:06:00 x jane
7 01-01-2021 12:07:00 end jane
8 01-01-2021 12:08:00 start todd
9 01-01-2021 12:09:00 x todd
10 01-01-2021 12:10:00 end todd
11 01-01-2021 12:11:00 start bob
12 01-01-2021 12:12:00 q bob
13 01-01-2021 12:13:00 end bob
14 01-01-2021 12:14:00 start ned
Довольно полосатое переднее бревно. Метки времени являются строками, но при необходимости их можно легко преобразовать в объекты datetime. В журнале перечислены различные действия, выполняемые пользователем, но меня интересует создание отчета о сеансах учетной записи пользователем. Что-то вроде этого:
account start end
0 bob 01-01-2021 12:00:00 01-01-2021 12:05:00
1 jane 01-01-2021 12:03:00 01-01-2021 12:07:00
2 todd 01-01-2021 12:08:00 01-01-2021 12:10:00
3 bob 01-01-2021 12:11:00 01-01-2021 12:13:00
4 ned 01-01-2021 12:14:00 NaN
Достаточно легко сгруппировать по времени начала и окончания, проблема, которую я не могу понять, заключается в том, как это сделать, когда у пользователя несколько сеансов за рассматриваемый период времени. В приведенных выше данных псевдо-журнала у Боба открыто 2 сеанса, но теоретически он мог открыть 100 сеансов в зависимости от диапазона дат данных, на которые я смотрю. Рассматриваемое приложение ограничивает пользователей 1 сеансом за раз, поэтому я не должен видеть одну и ту же учетную запись с 2 сеансами, открытыми одновременно.
Как мне сгруппировать время начала/окончания сеанса в 2 столбца, подобных этому, по учетной записи, когда в данных учетной записи может быть несколько сеансов?
Ответ №1:
Попробуй:
(df1.assign(idx=df1.event.eq('start').groupby(df1.account).cumsum()) # enumerate the `start` event by account
.loc[lambda x: x['event'].isin(['start','end'])] # only keep `start` and `end` events
.set_index(['idx','account','event']) # set index and unstack
['timestamp'].unstack() # then unstack
.reset_index(level=1).reset_index(drop=True) # tidying up
)
Выход:
event account end start
0 bob 01-01-2021 12:05:00 01-01-2021 12:00:00
1 jane 01-01-2021 12:07:00 01-01-2021 12:03:00
2 ned NaN 01-01-2021 12:14:00
3 todd 01-01-2021 12:10:00 01-01-2021 12:08:00
4 bob 01-01-2021 12:13:00 01-01-2021 12:11:00
Ответ №2:
Вы могли бы определить старты и использовать pivot_table
:
(df1.assign(idx=df1['event'].eq('start').groupby(df1['account']).cumsum())
.pivot_table(index=['account', 'idx'], columns='event', values='timestamp', aggfunc='first')
[['start', 'end']]
)
Выход:
event start end
account idx
bob 1 01-01-2021 12:00:00 01-01-2021 12:05:00
2 01-01-2021 12:11:00 01-01-2021 12:13:00
jane 1 01-01-2021 12:03:00 01-01-2021 12:07:00
ned 1 01-01-2021 12:14:00 NaN
todd 1 01-01-2021 12:08:00 01-01-2021 12:10:00
Комментарии:
1. Извините, забыл обновить сообщение раньше. Это сработало, спасибо!