2016-12-29 9 views
1

Ich habe ein Datenrahmen, die auf Produktspeicher day_id Ebene gruppiert Sagen Sie es wie unten aussieht und ich brauche eine Spalte mit Roll SummeSumme der nächsten n Zeilen in Python

prod store day_id visits 
111 123 1   2 
111 123 2   3 
111 123 3   1 
111 123 4   0 
111 123 5   1 
111 123 6   0 
111 123 7   1 
111 123 8   1 
111 123 9   2 

Notwendigkeit der Schaffung eines Datenrahmen erstellen wie unten

prod store day_id visits rolling_4_sum cond 
111 123 1   2 6    1 
111 123 2   3 5    1 
111 123 3   1 2    1 
111 123 4   0 2    1 
111 123 5   1 4    0 
111 123 6   0 4    0 
111 123 7   1 NA    0 
111 123 8   1 NA    0 
111 123 9   2 NA    0 

i für erstellen cond Spalte Suche: die rekursiv eine Bedingung überprüft, sagen, wenn rolling_4_sum größer als 5 dann die nächsten 4 Reihen machen als 1 sonst nichts tun, das heißt Auch wenn die Bedingung nicht erfüllt ist, behalten Sie, was bereits vorher ausgefüllt wurde, diese Prüfung für jede Zeile bis zur 7. Zeile.

Wie kann ich dies mit Python erreichen? Ich versuche

d1['rolling_4_sum'] = d1.groupby(['prod', 'store']).visits.rolling(4).sum() 

aber immer einen Fehler.

+0

Wenn du eine rollende Summe willst, solltest du die 'sum' Methode anstelle der' mean' Methode verwenden. – lmo

+0

ja, korrigiert, aber immer noch die folgenden TypeError: inkompatibler Index der eingefügten Spalte mit Frame-Index – Mukul

+0

Ihr Fehler ist wegen groupby. Es macht keinen Sinn, die Daten nach einigen Spalten zu gruppieren und sie dann wieder in denselben Datenrahmen zu stellen. Wenn es gruppiert ist, ist das ein neuer Datenrahmen mit einem eigenen Index, also arbeite mit diesem. – FTP

Antwort

2

Die Bildung von Walz Summen kann mit rolling Verfahren erfolgen, Boxcar Fenster mit:

df['rolling_4_sum'] = df.visits.rolling(4, win_type='boxcar', center=True).sum().shift(-2) 

Die Verschiebung von -2 ist, weil Sie offenbar die Summen am linken Rand des Fensters platziert werden soll.

Als nächstes wird der Zustand über Roll Summen kleiner als 4:

df['cond'] = 0 
for k in range(1, 4): 
    df.loc[df.rolling_4_sum.shift(k) < 7, 'cond'] = 1 

wird eine neue Spalte eingefügt und gefüllt mit 0; dann für jedes k = 1,2,3,4, schaue k Schritte zurück; Wenn die Summe dann kleiner als 7 ist, dann setze die Bedingung auf 1.

+0

danke zaq, Rolling Teil funktioniert sehr gut, jedoch gab es einen Fehler in meiner Frage, der Zustand war df.loc [df.rolling_4_sum> 5] und nicht 4, ich wollte die nächsten 4 Zeilen als 1, und nicht die vorherige 4, auch ich bemerkte, deine 2. Frage verschiebt die ganzen Daten, 4 Reihen zurück. es sollte die Verschiebung der ganzen Daten nicht zurück ändern. – Mukul

+0

Okay, also habe ich 4 durch 7 ersetzt. 'Df.shift' ändert df nicht, es gibt eine Kopie mit verschobenen Zeilen zurück. Ich hatte einen Zeichenfehler in diesem: es sollte 'shift (k)' sein. Die Bedeutung ist, dass wir nach shift (k) die Daten k Schritte zurück betrachten und damit entscheiden, ob cond geändert werden soll. Der Effekt ist also, dass, wenn etwas <7 ist, die nächsten 4 Zeilen geändert werden. – FTP