J'ai 2 colonnes dans un dataframe pour lequel je veux calculer le cumprod pour les deux, mais le cumprod doit redémarrer une fois qu'il voit un na dans la cellule
J'ai essayé d'utiliser cumprod directement, mais cela ne me permet pas les valeurs correctes car le cumprod est continu et ne redémarre pas lorsque le na apparaît
Voici un exemple de df
index col1 col2 0 2 4 1 12 16 2 12 na 3 24 7 4 na 42 5 na 336 6 5 na 7 40 9 8 240 18
voici ma sortie souhaitée: / p>
index col1 col2 0 2 4 1 6 4 2 1 na 3 2 7 4 na 6 5 na 8 6 5 na 7 8 9 8 3 2
4 Réponses :
Voici une solution qui opère sur chaque colonne et concats ensemble, puisque les masques sont différents pour chaque colonne.
m = df.isnull().cumsum() pd.concat( [df[col].groupby(mask).cumprod() for col, mask in zip(df.columns, m.values.T)], axis=1)
p >
col1 col2 0 2.0 4.0 1 12.0 16.0 2 12.0 NaN 3 24.0 7.0 4 NaN 42.0 5 NaN 336.0 6 5.0 NaN 7 40.0 9.0 8 120.0 18.0
Une approche légèrement plus efficace consiste à calculer le masque de mérou en une seule fois et à utiliser zip
pd.concat( [df[col].groupby(df[col].isnull().cumsum()).cumprod() for col in df.columns], axis=1)
Vous pouvez utiliser groupby avec isna et cumsum pour obtenir des groupes à comprendre dans chaque colonne en utilisant apply :
col1 col2 index 0 2.0 4.0 1 12.0 16.0 2 12.0 NaN 3 24.0 7.0 4 NaN 42.0 5 NaN 336.0 6 5.0 NaN 7 40.0 9.0 8 120.0 18.0
Résultat:
df.apply(lambda x: x.groupby(x.isna().cumsum()).cumprod())
Voici une solution similaire avec dict comprehension et le constructeur par défaut
col1 col2 0 2.0 4.0 1 12.0 16.0 2 12.0 NaN 3 24.0 7.0 4 NaN 42.0 5 NaN 336.0 6 5.0 NaN 7 40.0 9.0 8 120.0 18.0
pd.DataFrame({c: df[c].groupby(df[c].isna().cumsum()).cumprod() for c in df.columns})
Voici une solution sans opérer colonne par colonne:
df = pd.DataFrame([[2,4], [6,4], [1,np.nan], [2,7], [np.nan,6], [np.nan,8], [5,np.nan], [8,9], [3,2]],
columns=['col1', 'col2'])
df_cumprod = df.cumprod()
adjust_factor = df_cumprod.fillna(method='ffill').where(df_cumprod.isnull()).fillna(method='ffill').fillna(1)
print(df_cumprod / adjust_factor)
col1 col2
0 2.0 4.0
1 12.0 16.0
2 12.0 NaN
3 24.0 7.0
4 NaN 42.0
5 NaN 336.0
6 5.0 NaN
7 40.0 9.0
8 120.0 18.0