Эффективный цикл в сгруппированном Dataframe для доступа к значениям текущего и предыдущего индекса (и расчета разницы) - PullRequest
0 голосов
/ 28 августа 2018

У меня большой фрейм данных, который выглядит как ниже. Данные отсортированы по идентификатору, за которым следует OnTime

    id  OnTime              OffTime
0   1   2017-08-01 09:38:17 2017-08-01 09:49:31
1   1   2017-08-01 09:53:15 2017-08-01 09:54:50
2   1   2017-08-01 09:57:29 2017-08-01 10:10:42
3   2   2017-08-01 09:02:00 2017-08-01 09:27:15
4   2   2017-08-01 09:29:15 2017-08-01 09:43:41

Мне нужно рассчитать разницу во времени между текущим OnTime и предыдущим OffTime, если идентификаторы совпадают. (эта разница называется timeSince)

В поисках эффективного способа сделать это на Python. Фрейм данных имеет около 400 тыс. Строк. Я думал о группировке по идентификаторам по я не совсем уверен, как я могу повторить и рассчитать разницу во времени.

Вывод должен выглядеть следующим образом:

timeSince
-1 #since this is the 1st row of ID 1 no previous OffTime exists
3.7333333333333334
2.65
-1 #since this is the 1st row of ID 2 no previous OffTime exists
2.0

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

заманчиво использовать GroupBy + lambda, но не обязательно:

df['timeSince'] = (df['OnTime'] - df.groupby('id')['OffTime'].shift())
df['timeSince'] = (df['timeSince'] / np.timedelta64(1, 'm')).fillna(-1)

print(df)

              OffTime              OnTime  id  timeSince
0 2017-08-01 09:49:31 2017-08-01 09:38:17   1  -1.000000
1 2017-08-01 09:54:50 2017-08-01 09:53:15   1   3.733333
2 2017-08-01 10:10:42 2017-08-01 09:57:29   1   2.650000
3 2017-08-01 09:27:15 2017-08-01 09:02:00   2  -1.000000
4 2017-08-01 09:43:41 2017-08-01 09:29:15   2   2.000000
0 голосов
/ 28 августа 2018

Вы можете попробовать использовать apply, затем shift OffTime на 1. Поскольку выходное значение равно TimeDelta, нам нужно преобразовать его, используя apply, затем взять общее значение seconds и затем разделить на 60 (1minute = 60seconds). Наконец, используйте fillna, чтобы заполнить NaN значения -1, затем reset_index. Результат:

import pandas as pd

df['OnTime'] = pd.to_datetime(df['OnTime'])
df['OffTime'] = pd.to_datetime(df['OffTime'])

df['timeSince']=df.groupby('id').apply(lambda x: x['OnTime']-x['OffTime'].shift(1)).\
                                 apply(lambda x: x.seconds/60).fillna(-1).\
                                 reset_index(drop=True)
df

   id                OnTime             OffTime timeSince
0   1   2017-08-01 09:38:17 2017-08-01 09:49:31 -1.000000
1   1   2017-08-01 09:53:15 2017-08-01 09:54:50  3.733333
2   1   2017-08-01 09:57:29 2017-08-01 10:10:42  2.650000
3   2   2017-08-01 09:02:00 2017-08-01 09:27:15 -1.000000
4   2   2017-08-01 09:29:15 2017-08-01 09:43:41  2.000000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...