Dado el siguiente marco de datos:
+------------+--------+ | Date | Amount | +------------+--------+ | 01/05/2019 | 15 | | 27/05/2019 | 20 | | 27/05/2019 | 15 | | 25/06/2019 | 10 | | 29/06/2019 | 25 | | 01/07/2019 | 50 | +------------+--------+Necesito obtener la suma móvil de todas las fechas anteriores de la siguiente manera:
+------------+--------+ | Date | Amount | +------------+--------+ | 01/05/2019 | NaN | | 27/05/2019 | 15 | | 27/05/2019 | 15 | | 15/06/2019 | 35 | | 29/06/2019 | 10 | | 01/07/2019 | 35 | +------------+--------+Utilizando:
df = pd.DataFrame( { 'Date': { 0: datetime.datetime(2019, 5, 1), 1: datetime.datetime(2019, 5, 27), 2: datetime.datetime(2019, 5, 27), 3: datetime.datetime(2019, 6, 15), 4: datetime.datetime(2019, 6, 29), 5: datetime.datetime(2019, 7, 1), }, 'Amount': {0: 15, 1: 20, 2: 15, 3: 10, 4: 25, 5: 50} } ) df.sort_values("Date", inplace=True) df_roll = df.rolling("28d", on="Date", closed="left").sum()Me atrapa:
+------------+--------+ | Date | Amount | +------------+--------+ | 01/05/2019 | NaN | | 27/05/2019 | 15 | | 27/05/2019 | 35 | <-- Should be 15 | 15/06/2019 | 35 | | 29/06/2019 | 10 | | 01/07/2019 | 35 | +------------+--------+Lo cual no es del todo correcto.
¿Cómo obtendría la suma de todas las fechas anteriores en lugar de todas las filas anteriores?
Una forma es agregar sus cantidades por fecha primero, luego calcular la suma móvil y unir esta suma a la lista original de fechas para aplicar la suma móvil a todas las fechas.
# Aggregate (sum) by date df_agged = (df.groupby('Date')['Amount'].agg(['sum']) .reset_index() .rename(columns={'sum':'Amount'})) # Compute rolling sum df_agged_rolling = df_agged.rolling("28d",on="Date",closed='left').sum() # Join on original dates to apply rolling sum to duplicate dates df_with_rolling_agg = df.join(df_agged_rolling.set_index('Date'),on='Date', lsuffix='_orig',rsuffix='_rolling_sum') df_with_rolling_agg # Date Amount_orig Amount_rolling_sum # 0 2019-05-01 15 NaN # 1 2019-05-27 20 15.0 # 2 2019-05-27 15 15.0 # 3 2019-06-15 10 35.0 # 4 2019-06-29 25 10.0 # 5 2019-07-01 50 35.0Primero puede eliminar las fechas duplicadas, luego hacer una suma móvil y luego completar los NaN resultantes (ocasionados por la eliminación de duplicados):
df = df.assign(Amount=df.drop_duplicates(subset=['Date']).rolling("28d", on="Date", closed="left")['Amount'].sum()).ffill()Producción:
>>> df Date Amount 0 2019-05-01 NaN 1 2019-05-27 15.0 2 2019-05-27 15.0 3 2019-06-15 20.0 4 2019-06-29 10.0 5 2019-07-01 35.0Tu puedes hacer
df['new'] = df.Date.map(df.groupby('Date').Amount.sum().rolling("28d", closed="left").sum()) df Date Amount new 0 2019-05-01 15 NaN 1 2019-05-27 20 15.0 2 2019-05-27 15 15.0 3 2019-06-15 10 35.0 4 2019-06-29 25 10.0 5 2019-07-01 50 35.0