Присвоить значение на основе выходных данных предыдущей строки - PullRequest
2 голосов
/ 08 марта 2019

Я анализирую выходной журнал приложения с пандами и хочу назначить каждую запись в сеансе.Сессия определяется как 60-минутный период с начала.

Вот небольшой пример:

import numpy as np
import pandas as pd
from datetime import timedelta

> df = pd.DataFrame({
    'time': [
        pd.Timestamp(2019, 1, 1, 1, 10),
        pd.Timestamp(2019, 1, 1, 1, 15),
        pd.Timestamp(2019, 1, 1, 1, 20),
        pd.Timestamp(2019, 1, 1, 2, 20),
        pd.Timestamp(2019, 1, 1, 5, 0),
        pd.Timestamp(2019, 1, 1, 5, 15)
    ]
})

> df
                   time
0   2019-01-01 01:10:00
1   2019-01-01 01:15:00
2   2019-01-01 01:20:00
3   2019-01-01 02:20:00
4   2019-01-01 05:00:00
5   2019-01-01 05:15:00

Для первой строки start_time равно time.Для последующих строк, если его time находится в пределах 1 часа от предыдущей строки, он считается находящимся в том же сеансе.Если нет, то начнется новый сеанс с start_time = time.Я использую цикл:

df['start_time'] = np.nan

for index in df.index:
    if index == 0:
        start_time = df['time'][index]
    else:
        delta = df['time'][index] - df['time'][index - 1]
        start_time = df['start_time'][index - 1] if delta.total_seconds() <= 3600 else df['time'][index]

    df['start_time'][index] = start_time

Вывод:

                   time          start_time
0   2019-01-01 01:10:00 2019-01-01 01:10:00
1   2019-01-01 01:15:00 2019-01-01 01:10:00
2   2019-01-01 01:20:00 2019-01-01 01:10:00
3   2019-01-01 02:20:00 2019-01-01 01:10:00
4   2019-01-01 05:00:00 2019-01-01 05:00:00 # new session
5   2019-01-01 05:15:00 2019-01-01 05:00:00

Работает, но очень медленно.Есть ли способ векторизовать его?

Ответы [ 2 ]

2 голосов
/ 08 марта 2019

Используя diff с cumsum, создайте ключ группы, затем мы просто используем этот ключ, чтобы получить значение first каждой группы

s=(df.time.diff()/np.timedelta64(1, 's')).gt(3600).cumsum()
df.groupby(s)['time'].transform('first')
Out[833]: 
0   2019-01-01 01:10:00
1   2019-01-01 01:10:00
2   2019-01-01 01:10:00
3   2019-01-01 01:10:00
4   2019-01-01 05:00:00
5   2019-01-01 05:00:00
Name: time, dtype: datetime64[ns]
df['statr_time']=df.groupby(s)['time'].transform('first')
1 голос
/ 08 марта 2019

Я использовал np where, shift и cumsum для создания идентификатора сеанса.Затем я использовал преобразование и мин, чтобы получить время начала

df['session_id'] = np.where((df['time'] - df['time'].shift(1)).astype('timedelta64[m]').fillna(0)>60,1,0).cumsum()
df['start_time'] = df.groupby(['session_id'])['time'].transform(min)

display(df)

    time    session_id  start_time
0   2019-01-01 01:10:00 0   2019-01-01 01:10:00
1   2019-01-01 01:15:00 0   2019-01-01 01:10:00
2   2019-01-01 01:20:00 0   2019-01-01 01:10:00
3   2019-01-01 02:20:00 0   2019-01-01 01:10:00
4   2019-01-01 05:00:00 1   2019-01-01 05:00:00
5   2019-01-01 05:15:00 1   2019-01-01 05:00:00
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...