Помощь с подсчётом в датасете pandas
Имеется следующий датасет:
| date | user | event_type | parameter | |
|---|---|---|---|---|
| 0 | 2020-04-01_00:01:08 770906 | 770906 | 3 | unknown |
| 1 | 2020-04-01_00:00:30 527877 | 527877 | 1 | text |
| 2 | 2020-04-01_00:01:12 539948 | 539948 | 3 | picture |
| 3 | 2020-04-01_00:01:20 107541 | 107541 | 3 | picture |
| 4 | 2020-04-01_00:01:38 374954 | 374954 | 4 | text |
Надо найти день, когда число уникальных пользователей, отправивших текстовое сообщение (event_type=4, parameter=text), было максимальным.
Также нужно определить 20-минутный интервал [time; time + 20 min), в течение которого произошло больше всего событий? Если таких интервалов несколько, нужно найти начало самого позднего.
Описание переменных:
date object
user int64
event_type int64
parameter object
dtype: object
Ответы (1 шт):
Создадим DataFrame по подобию:
import pandas as pd
import numpy as np
from random import randint as r
day = lambda : "%02d" % r(1,30)
hour = lambda : "%02d" % r(0,23)
min_sec = lambda : "%02d" % r(0,59)
user = lambda : "%06d" % r(100000,999999)
rows_c=100000
df = pd.DataFrame({
'date': ['2020-04-{}_{}:{}:{}'.format(day(),hour(),min_sec(),min_sec()) for _ in range(0,rows_c)],
'user': ["%06d" % r(100000,999999) for _ in range(0,rows_c)],
'event_type': [r(1,4) for _ in range(0,rows_c)],
'parameter': [['unknown', 'text', 'picture'][r(0,2)] for _ in range(0,rows_c)]
})
df.date = df.date + ' ' + df.user
df
Вывод:
date user event_type parameter
0 2020-04-08_16:12:07 395528 395528 2 text
1 2020-04-10_21:10:21 682091 682091 2 unknown
2 2020-04-30_15:06:42 738315 738315 3 picture
3 2020-04-01_20:09:04 723756 723756 2 picture
4 2020-04-20_09:04:02 859750 859750 4 unknown
... ... ... ... ...
99995 2020-04-05_01:45:29 801973 801973 2 picture
99996 2020-04-07_05:48:39 379318 379318 2 text
99997 2020-04-11_04:24:33 581294 581294 2 picture
99998 2020-04-13_13:17:48 807151 807151 4 text
99999 2020-04-24_10:34:03 362205 362205 2 text
100000 rows × 4 columns
Задача 1
Надо найти день, когда число уникальных пользователей, отправивших текстовое сообщение (
event_type=4,parameter=text), было максимальным.
В первую очередь приведём колонку date к формату datetime. Затем делаем фильтр по event_type и parameter. Убираем дубликаты из user, чтобы получить уникальных пользователей. Делаем groupby по дням и выводим день в котором было больше всего этих пользователей.
df.date = df.date.str.replace(r'\s.*','', regex=True)
df.date = pd.to_datetime(df.date, format='%Y-%m-%d_%H:%M:%S')
filtered_df = df[(df.event_type == 4) & (df.parameter == 'text')]
filtered_df = filtered_df.drop_duplicates(subset=['user'])
filtered_df.groupby(df.date.dt.day).size().idxmax()
Вывод:
10
Задача 2
Также нужно определить 20-минутный интервал [time; time + 20 min), в течение которого произошло больше всего событий? Если таких интервалов несколько, нужно найти начало самого позднего.
Интервал нужно определить на отфильтрованной таблице? Далее код работает с неотфильтрованной, т.к. из задачи не ясно.
max_c = 0
for x in df.index:
count = df.date[(df.date >= df.date.loc[x]) & (df.date < df.date.loc[x] + pd.Timedelta(20, "m"))].count()
if count > max_c:
ixs = [x]
max_c = count
elif count == max_c:
ixs.append(x)
df.loc[ixs].date.idxmax()
Вывод:
76910
Получили index наиболее позднего события в интервале 20-и минут которого было наибольшее количество событий.
Сами события можно вывести через:
ix = df.loc[ixs].date.idxmax()
df[(df.date >= df.date.loc[ix]) & (df.date < df.date.loc[ix] + pd.Timedelta(20, "m"))]
Делать итератор, конечно, не очень хорошо, можно было бы сделать через:
df.index = df.date
gr = df.groupby([pd.Grouper(freq='20min')])
Но в подходе с итератором я больше уверен.