Разница во времени между строкой и ее предыдущей / следующей строкой для одного и того же покупателя в кадре данных pandas - PullRequest
3 голосов
/ 30 мая 2019

У меня есть фрейм данных:

In [1]: import pandas as pd;import numpy as np                                              

In [2]: df = pd.DataFrame( 
   ...: [ 
   ...:     ['A', '2019-05-10 23:59:59', 'NOT_WORKING'], 
   ...:     ['A', '2019-05-11 00:05:00', 'WORKING'], 
   ...:     ['B', '2019-05-13 07:55:00', 'NOT_WORKING'], 
   ...:     ['B', '2019-05-15 07:57:00', 'WORKING'], 
   ...:     ['B', '2019-05-16 08:03:00', 'NOT_WORKING'], 
   ...: ], columns=['cust', 'event_date', 'status']) 
   ...: df.event_date = pd.to_datetime(df.event_date)                    

In [3]: df.loc[1, 'test'] = 'Y' 
   ...: df.loc[3, 'test'] = 'Y'                                          

In [4]: df                                                               
Out[4]: 
  cust          event_date       status test
0    A 2019-05-10 23:59:59  NOT_WORKING  NaN
1    A 2019-05-11 00:05:00      WORKING    Y
2    B 2019-05-13 07:55:00  NOT_WORKING  NaN
3    B 2019-05-15 07:57:00      WORKING    Y
4    B 2019-05-16 08:03:00  NOT_WORKING  NaN

Мне нужно выяснить разницу во времени между тестовыми строками и их предыдущими / следующими строками для одного и того же клиента.

Я сделал это так:

In [5]: df.loc[:, 'prev_time'] = df.event_date.shift(1) 
   ...: df.loc[:, 'prev_cust'] = df.cust.shift(1) 
   ...: df.loc[:, 'next_time'] = df.event_date.shift(-1) 
   ...: df.loc[:, 'next_cust'] = df.cust.shift(-1) 
   ...: df                                                               
Out[5]: 
  cust          event_date  ...           next_time next_cust
0    A 2019-05-10 23:59:59  ... 2019-05-11 00:05:00         A
1    A 2019-05-11 00:05:00  ... 2019-05-13 07:55:00         B
2    B 2019-05-13 07:55:00  ... 2019-05-15 07:57:00         B
3    B 2019-05-15 07:57:00  ... 2019-05-16 08:03:00         B
4    B 2019-05-16 08:03:00  ...                 NaT       NaN

[5 rows x 8 columns]

In [9]: df = df.loc[df.test=='Y', :].assign(time_to_prev=lambda row: row.
   ...: event_date - row.prev_time ).assign(time_to_next=lambda row: row.
   ...: next_time - row.event_date) 
   ...: df.loc[df.cust != df.prev_cust, 'time_to_prev'] = np.nan 
   ...: df.loc[df.cust != df.next_cust, 'time_to_next'] = np.nan 
   ...: df = df.drop(columns=['prev_time', 'prev_cust', 'next_time', 'nex
   ...: t_cust']) 
   ...: df                                                               
Out[9]: 
  cust          event_date   status test    time_to_prev    time_to_next
1    A 2019-05-11 00:05:00  WORKING    Y 0 days 00:05:01             NaT
3    B 2019-05-15 07:57:00  WORKING    Y 2 days 00:02:00 1 days 00:06:00

Это работает, но я ищу более элегантное решение, которое будет включать groupby, diff ... Как это сделать?

Ответы [ 2 ]

1 голос
/ 30 мая 2019

Используйте DataFrameGroupBy.diff для столбца time_to_prev, затем DataFrameGroupBy.shift для time_to_next и только последний фильтр Y строк по boolean indexing:

#if not sorted customers with datetimes column
#df = df.sort_values(['cust', 'event_date'])
df['time_to_prev'] = df.groupby('cust')['event_date'].diff()
df['time_to_next'] = df.groupby('cust')['time_to_prev'].shift(-1)

df = df[df.test=='Y'].copy()
print (df)          
  cust          event_date   status test    time_to_prev    time_to_next
1    A 2019-05-11 00:05:00  WORKING    Y 0 days 00:05:01             NaT
3    B 2019-05-15 07:57:00  WORKING    Y 2 days 00:02:00 1 days 00:06:00
1 голос
/ 30 мая 2019

Сначала просто убедитесь, что сортировка верна для 'cust' и 'event_date', а затем для группового клиента, затем возьмите разницу для каждой строки.

df = df.sort_values(['cust', 'event_date'])
df.groupby('cust')['event_date'].diff()


       event_date
0             NaT
1 0 days 00:05:01
2             NaT
3 2 days 00:02:00
4 1 days 00:06:00
...