Pandas equivalentes a la función Oracle Lead / Lag

Primero soy nuevo en pandas, pero ya me estoy enamorando de eso. Estoy tratando de implementar el equivalente de la función Lag de Oracle.

Supongamos que tiene este DataFrame:

Date Group Data 2014-05-14 09:10:00 A 1 2014-05-14 09:20:00 A 2 2014-05-14 09:30:00 A 3 2014-05-14 09:40:00 A 4 2014-05-14 09:50:00 A 5 2014-05-14 10:00:00 B 1 2014-05-14 10:10:00 B 2 2014-05-14 10:20:00 B 3 2014-05-14 10:30:00 B 4 

Si se tratara de una base de datos de Oracle y quisiera crear una función de retraso agrupada por la columna “Grupo” y ordenada por la Fecha en la que podría usar esta función fácilmente:

  LAG(Data,1,NULL) OVER (PARTITION BY Group ORDER BY Date ASC) AS Data_lagged 

Esto daría lugar a la siguiente tabla:

 Date Group Data Data lagged 2014-05-14 09:10:00 A 1 Null 2014-05-14 09:20:00 A 2 1 2014-05-14 09:30:00 A 3 2 2014-05-14 09:40:00 A 4 3 2014-05-14 09:50:00 A 5 4 2014-05-14 10:00:00 B 1 Null 2014-05-14 10:10:00 B 2 1 2014-05-14 10:20:00 B 3 2 2014-05-14 10:30:00 B 4 3 

En pandas puedo establecer la fecha para que sea un índice y usar el método de cambio:

 db["Data_lagged"] = db.Data.shift(1) 

El único problema es que esto no se agrupa por una columna. Incluso si configuro las dos columnas Fecha y Grupo como índices, todavía obtendría el “5” en la columna retrasada.

¿Hay alguna manera de implementar el equivalente de las funciones de adelanto y retraso en Pandas?

Usted podría realizar una operación groupby / apply (shift) :

 In [15]: df['Data_lagged'] = df.groupby(['Group'])['Data'].shift(1) In [16]: df Out[16]: Date Group Data Data_lagged 2014-05-14 09:10:00 A 1 NaN 2014-05-14 09:20:00 A 2 1 2014-05-14 09:30:00 A 3 2 2014-05-14 09:40:00 A 4 3 2014-05-14 09:50:00 A 5 4 2014-05-14 10:00:00 B 1 NaN 2014-05-14 10:10:00 B 2 1 2014-05-14 10:20:00 B 3 2 2014-05-14 10:30:00 B 4 3 [9 rows x 4 columns] 

Para obtener el efecto ORDER BY Date ASC , primero debe ordenar el DataFrame:

 df['Data_lagged'] = (df.sort_values(by=['Date'], ascending=True) .groupby(['Group'])['Data'].shift(1))