Buscar días desde el último evento.

Tengo un dataframe pandas:

df12 = pd.DataFrame({'group_ids':[1,1,1,2,2,2],'dates':['2016-04-01','2016-04-20','2016-04-28','2016-04-05','2016-04-20','2016-04-29'],'event_today_in_group':[1,0,1,1,1,0]}) group_ids dates event_today_in_group 0 1 2016-04-01 1 1 1 2016-04-20 0 2 1 2016-04-28 1 3 2 2016-04-05 1 4 2 2016-04-20 1 5 2 2016-04-29 0 

Me gustaría calcular una columna adicional que contenga, para cada group_ids, el número de días desde la última vez que event_today_in_group fue 1.

  group_ids dates event_today_in_group days_since_last_event 0 1 2016-04-01 1 0 1 1 2016-04-20 0 19 2 1 2016-04-28 1 27 3 2 2016-04-05 1 0 4 2 2016-04-20 1 15 5 2 2016-04-29 0 9 

Como mencioné anteriormente, esto le dará la diferencia no acumulativa entre las fechas dentro de cada grupo:

 df['days_since_last_event'] = df.groupby('group_ids')['dates'].diff().apply(lambda x: x.days) 

Para obtener una sum acumulativa de esta diferencia, en función de cada event_today_in_group cambie event_today_in_group , propongo usar shift para obtener el valor de la fila anterior, y luego generar una sum acumulada, como así:

 df['event_today_in_group'].shift().cumsum() 

Salida:

 0 NaN 1 1.0 2 1.0 3 2.0 4 3.0 5 4.0 

Esto nos da el segundo valor de agrupación que necesitamos para obtener las sums acumuladas. Podría asignar los valores anteriores a una nueva columna, pero si solo los está utilizando para el cálculo, simplemente puede incluirlos en la siguiente operación de groupby la siguiente manera:

 df.loc[:, 'days_since_last_event'] = df.groupby(['group_ids', df['event_today_in_group'].shift().cumsum()])['days_since_last_event'].cumsum() 

Resultado:

  group_ids dates event_today_in_group days_since_last_event 0 1 2016-04-01 1 NaN 1 1 2016-04-20 0 19.0 2 1 2016-04-28 1 27.0 3 2 2016-04-05 1 NaN 4 2 2016-04-20 1 15.0 5 2 2016-04-29 0 9.0 

No estoy seguro sobre el uso de aplicar en la solución anterior, lo que lo hace terriblemente lento, lo he usado en competiciones Kaggle con grandes conjuntos de datos y funciona muy bien

 train_df['_time_since_last_event'] = train_df.sort_values(['GroupID', 'EventTime']).groupby('GroupID')['EventTime'].diff()