Tengo un marco de datos que se parece a esto:
grp val run
a 5 10
b 10 1
a NaN 8
a NaN 4
b NaN 5
b NaN 4
a 10 6
a NaN 6
Quiero llenar los espacios en la val
columna aplicando el mismo cambio porcentual que se calculó. Sin embargo, también necesito agrupar usando la grp
columna. Debería terminar con algo como esto:
grp val run
a 5 10
b 10 1
a 4 8
a 2 4
b 50 5
b 40 4
a 10 6
a 10 6
Solo quiero reemplazar valores que son nulos. Observe que el 10 en la fila siete "restablece" el relleno hacia adelante.
Sin tener que agrupar, podría simplemente obtener el cambio porcentual run
y multiplicar la val
celda de la fila anterior por la celda de cambio porcentual de la fila actual donde val
no sea nulo.
Estaba pensando que podría ordenar el marco de datos usando grp
, pero luego todavía tendría que preocuparme por el caso límite de cuando los grp
valores cambian.
Intentemos:
# identify the na blocks and group by `grp` and these blocks
na_blocks = df['val'].notna().groupby(df['grp']).cumsum()
g = df.groupby(['grp', na_blocks])
# "pct change" on run
df['x'] = df['run'] / g['run'].shift(fill_value=1)
# cumprod() for cumulative change
# `ffill` and `transform('first')` behave the same
# since we are grouping on non-nan following by consecutive nan's
df['val'] = g['val'].ffill() * g['x'].cumprod() / g['run'].transform('first')
Salida ( x
la columna adicional que se puede quitar):
grp val run x
0 a 5.0 10 10.0
1 b 10.0 1 1.0
2 a 4.0 8 0.8
3 a 2.0 4 0.5
4 b 50.0 5 5.0
5 b 40.0 4 0.8
6 a 10.0 6 6.0
7 a 10.0 6 1.0
Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.
En caso de infracción, por favor [email protected] Eliminar
Déjame decir algunas palabras