2017-07-19 9 views
1

Ich habe einen Pandas DataFrame (df) mit Informationen, die ich basierend auf Informationen in einem anderen Pandas DataFrame (dfIdx) mit den gleichen Spalten und Index summieren möchte. Insbesondere nimmt, wenn df die folgende Form:Kumulative Summe Pandas DataFrame mit Indikator DataFrame

df = pd.DataFrame([[172770, 1442, 114581],[35464, 67062, 175285],[124399, 14294, 44104],[50608, 58802, 189253],[1000, 10000, 100000]],columns=['A','B','C']) 

und dfIdx der folgenden Form:

dfIdx = pd.DataFrame([[0, 0, 1], [0, 0, 0], [0, 1, 0], [1, 1, 0],[0,0,1]],columns=['A','B','C']) 

ich das Ergebnis will die kumulative Summe der Zeilen in df vorangehen und die Zeilen zu sein in dfIdx mit einem Wert von 1. So sollte das Ergebnis wie folgt aussehen:

 A  B  C 
0  0  0 114581 
1  0  0  0 
2  0 82798  0 
3 383241 58802  0 
4  0  0 508642 

Für zusätzliche Kredite, ich möchte flexibel sein, in Bezug auf, wie weit zurück die kumulative Summe enthält Beiträge. wenn das Fenster für die kumulative Summe zum Beispiel 1 ist, dann würde ich nur höchstens eine vorhergehende Zeile enthalten mögen, das Ergebnis geben:

 A  B  C 
0  0  0 114581 
1  0  0  0 
2  0 81356  0 
3 175007 58802  0 
4  0  0 289253 

Ich weiß, das ursprüngliche Beispiel habe ich nicht bieten alle Beispiele für Verhalten, das ich wollte, und als Ergebnis war die vorgeschlagene Lösung unvollständig. Ich habe die Daten um eine weitere Zeile erweitert, um ein vielfältigeres Verhalten zu ermöglichen.

+0

Wenn es hilft, verwenden Sie die vorgeschlagene Lösung by @ScottBoston unten scheint zu funktionieren, wenn ich seine 'df_group' ändere, um' dfIdx.loc [list (reversed (dfIdx.index))]]. cumsum(). loc [dfIdx.index, x.name] 'zu sein. Irgendwelche anderen Vorschläge? – DrTRD

Antwort

2

EDIT neue Anforderungen und erweiterte Datenmenge

df_out = (df.apply(lambda x: x.groupby(dfIdx.loc[::-1,x.name].cumsum().replace(0,pd.np.nan).bfill()) 
          .transform('cumsum') 
          .mul(dfIdx[x.name]))) 

Ausgabe gerecht zu werden:

 A  B  C 
0  0  0 114581 
1  0  0  0 
2  0 82798  0 
3 383241 58802  0 
4  0  0 508642 

Update für zusätzliche Kredite:

n=1 #for summing 1 pervious value 
df_out = (df.apply(lambda x: x.groupby(dfIdx.loc[::-1,x.name].cumsum().replace(0,pd.np.nan).bfill()) 
           .rolling(n+1,min_periods=1).sum().reset_index(level=0,drop=True) 
           .mul(dfIdx[x.name]))) 

Ausgang:

  A  B   C 
0  0.0  0.0 114581.0 
1  0.0  0.0  0.0 
2  0.0 81356.0  0.0 
3 175007.0 58802.0  0.0 
4  0.0  0.0 289253.0 

Hinweis: Sie waren so nahe an Ihrer Beobachtung mit reversed. Ich mache das Gleiche. Es geht darum, wie Sie diesen dfIdx gruppieren.


Lassen Sie uns versuchen:

df_out = (df.apply(lambda x: x.groupby(dfIdx[x.name].cumsum().replace(0,pd.np.nan).bfill()) 
          .transform('cumsum') 
          .mul(dfIdx[x.name]))) 

Ausgang:

 A  B  C 
0  0  0 114581 
1  0  0  0 
2  0 82798  0 
3 383241 58802  0 

Und für "zusätzliche Kredite", wobei n = 1, wir eine Rollperiode von 2 verwenden:

n=1 #for summing 1 pervious value 
df_out = (df.apply(lambda x: x.groupby(dfIdx[x.name].cumsum().replace(0,pd.np.nan).bfill()) 
           .rolling(n+1,min_periods=1).sum().reset_index(level=0,drop=True) 
           .mul(dfIdx[x.name]))) 

Ausgabe:

  A  B   C 
0  0.0  0.0 114581.0 
1  0.0  0.0  0.0 
2  0.0 81356.0  0.0 
3 175007.0 58802.0  0.0 

Wie?

1 Schritt die Gruppierung in dfIdx erhalten:

df_group = dfIdx.cumsum()\ 
    .replace(0,pd.np.nan)\ 
    .bfill() 

    A B C 
0 1.0 1.0 1 
1 1.0 1.0 1 
2 1.0 1.0 1 
3 1.0 2.0 1 

Schritt 2 Verwenden Sie die 'Transformation' oder 'rolling' auf df zu tun Gruppierung.

df_out = df.apply(lambda x: x.groupby(df_group)        
    .rolling(n+1,min_periods=1) 
    .sum() 
    .reset_index(level=0,drop=True)) 

      A  B   C 
0 172770.0 1442.0 114581.0 
1 208234.0 68504.0 289866.0 
2 159863.0 81356.0 219389.0 
3 175007.0 58802.0 233357.0 

Schritt 3 Lassen Sie uns Maske oder diese Werte mit 0 in dfIdx ausgerichtet ersetzen, können wir mehrere

df_out.mul (dfIdx)

  A  B   C 
0  0.0  0.0 114581.0 
1  0.0  0.0  0.0 
2  0.0 81356.0  0.0 
3 175007.0 58802.0  0.0