Задать вопрос
@immelnikoff
Изучаю БД

Как в pandas объединить непрерывную последовательность событий одного типа в интервал?

Имеется DataFrame:

user_id EventType EventTime
0 1 impression 2022-07-25 02:21:17
1 1 impression 2022-07-25 02:21:19
2 1 impression 2022-07-25 02:25:19
3 1 click 2022-07-25 02:26:25
4 1 click 2022-07-25 02:27:17
5 1 impression 2022-07-25 02:27:18
6 1 click 2022-07-25 02:29:18


Нужно получить след. DataFrame, в котором последовательные серии собыйти одного типа сгруппированы в одну строку:
user_id EventType first last
0 1 impression 2022-07-25 02:21:17 2022-07-25 02:25:19
1 1 click 2022-07-25 02:26:25 2022-07-25 02:27:17
2 1 impression 2022-07-25 02:27:18 2022-07-25 02:27:18
3 1 click 2022-07-25 02:29:18 2022-07-25 02:29:18
  • Вопрос задан
  • 104 просмотра
Подписаться 1 Средний Комментировать
Решения вопроса 1
Maksim_64
@Maksim_64
Data Analyst
Давай по порядку пандас запрос который решает вопрос.
(
    df
    .assign(
        groups=(df['EventType'] != df['EventType'].shift())
        .cumsum()
    )
    .groupby('groups'
    )
    .agg(
        first= pd.NamedAgg(column='EventTime',aggfunc=lambda x: np.min(x)),
        last= pd.NamedAgg(column='EventTime',aggfunc=lambda x: np.max(x)),
        EventType= pd.NamedAgg(column='EventType',aggfunc=lambda x: set(x).pop()),
        user_id=pd.NamedAgg(column='user_id',aggfunc=lambda x: set(x).pop()),
        )
    .reset_index(drop=True)
    .loc[:,['user_id','EventType','first','last']]
)


Ключевая история это группировка с последовательно повторяющимися значениями. Вот этот запрос по сути решает весь вопрос
(
    df
    .groupby(
        (df["EventType"] != df["EventType"].shift())
        .cumsum()
    )
    .agg({"EventTime" : ["min", "max"]})
)
Остальное это манипуляции для идентичного твоему вывода (писал на скорую руку совместил агрегации с трансформациями) что не есть хорошо, я бы поработал и сделал лучше. В целом сработает и для строк, но лучше привести EventTime к типу данных datetime64[ns]. Сделать это можно
(
    df.assign(
        EventTime=lambda x: pd.to_datetime(x['EventTime'],format='%Y-%m-%d %H:%M:%S')
    )
   ... 
)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы