2017-03-20 12 views
3

Ich habe ein DataFrame in pandas wie unten gezeigt:Looping durch vorherigen Wert in pandas multiplizieren

df = pd.DataFrame({'origin_dte':['2009-08-01','2009-08-01','2009-08-01','2009-08-01','2009-09-01','2009-09-01','2009-09-01'], 
        'date':['2009-08-01','2009-08-02','2009-08-03','2009-08-04','2009-09-01','2009-09-02','2009-09-03'], 
        'bal_pred':[10.,11.,12.,13.,21.,22.,23.], 
        'dbal_pred':[np.nan,.25,.3,.5,np.nan,.4,.45]}) 

    bal_pred date dbal_pred origin_dte 
0 10  2009-08-01 NaN  2009-08-01 
1 11  2009-08-02 0.25 2009-08-01 
2 12  2009-08-03 0.30 2009-08-01 
3 13  2009-08-04 0.50 2009-08-01 
4 21  2009-09-01 NaN  2009-09-01 
5 22  2009-09-02 0.40 2009-09-01 
6 23  2009-09-03 0.45 2009-09-01 

I Schleife möge und jede durch Beobachtung des bal_pred wo dbal_pred != NaN mit dbal_pred[i] * bal_pred[i-1] ersetzen. Zum Beispiel würde der zweite Wert von bal_pred0.25*10=2.5 werden. Wenn sich origin_dte ändert, also wieder NaN ist, würde die Berechnung die NaN Beobachtung überspringen und die nächste bal_pred berechnen. So würde df wie unten gezeigt aussehen. Ich habe eine while-Schleife, die das tut, aber das Problem ist, dass es sehr lange dauert, große Datenrahmen zu durchlaufen. Schätzen Sie einen einfacheren/schnelleren Weg!

bal_pred date  dbal_pred origin_dte 
0 10.000 2009-08-01 NaN  2009-08-01 
1 2.500  2009-08-02 0.25 2009-08-01 
2 0.750  2009-08-03 0.30 2009-08-01 
3 0.375  2009-08-04 0.50 2009-08-01 
4 21.000 2009-09-01 NaN  2009-09-01 
5 8.400  2009-09-02 0.40 2009-09-01 
6 3.780  2009-09-03 0.45 2009-09-01 

Antwort

2
# fillna with 1 so we can cumprod 
c = df.dbal_pred.fillna(1).cumprod() 

# track where null 
n = df.dbal_pred.isnull() 

# take cumprod where null and forward fill 
d = c.where(n).ffill() 

# cumprods divided by cumprod where last null 
# gets us a grouped cumprod that starts over 
# at every null. 
# multiply this by `bal_pred` where null forward filled 
# and voila 
df.assign(bal_pred=c.div(d) * df.bal_pred.where(n).ffill()) 

    bal_pred  date dbal_pred origin_dte 
0 10.000 2009-08-01  NaN 2009-08-01 
1  2.500 2009-08-02  0.25 2009-08-01 
2  0.750 2009-08-03  0.30 2009-08-01 
3  0.375 2009-08-04  0.50 2009-08-01 
4 21.000 2009-09-01  NaN 2009-09-01 
5  8.400 2009-09-02  0.40 2009-09-01 
6  3.780 2009-09-03  0.45 2009-09-01 
3

Ein anderer Ansatz wäre jede Gruppe von Daten zu kennzeichnen und dann das kumulative Produkt jeder Gruppe nehmen

group = df['dbal_pred'].isnull().cumsum() 
df.dbal_pred.fillna(df.bal_pred, inplace=True) 
df['bal_pred'] = df.groupby(group)['dbal_pred'].cumprod() 

Ausgang

bal_pred  date dbal_pred origin_dte 
0 10.000 2009-08-01  NaN 2009-08-01 
1  2.500 2009-08-02  0.25 2009-08-01 
2  0.750 2009-08-03  0.30 2009-08-01 
3  0.375 2009-08-04  0.50 2009-08-01 
4 21.000 2009-09-01  NaN 2009-09-01 
5  8.400 2009-09-02  0.40 2009-09-01 
6  3.780 2009-09-03  0.45 2009-09-01 
+0

Dank und guten Fang! –