2017-06-20 3 views
3

Ich habe eine große pandas Datenframe df mit Lager Daten zeigt Mengen der empfangenen Artikel.Pandas - Aggregat Teil der Spalte auf neuen Wert in der neuen Spalte

Stellen Sie sich den entsprechenden Teil der Struktur als:

Date   SKU received 
2017-05-29 sku1 0 
2017-05-30 sku1 0 
2017-05-31 sku1 0 
2017-06-01 sku1 0 
2017-06-02 sku1 6 
2017-06-03 sku1 2 
2017-05-29 sku2 4 
2017-05-30 sku2 4 
2017-05-31 sku2 0 
2017-06-01 sku2 0 
2017-06-02 sku2 0 
2017-06-03 sku2 24 

Von hier würde ich den Bestellprozess rekonstruieren möchte. Ich weiß, dass der Lagerbestand an Montagen überprüft wird, basierend auf dem Lagerbestand werden neue Aufträge platziert. Etwa eine Woche später kommen die Bestellungen im Lager an, manchmal aufgeteilt in mehrere Lieferungen.

Ich dachte an das Erstellen einer zusätzlichen Spalte für die Wochentage (df["Weekday"]) und für die erteilten Bestellungen (df["Order"]). Basierend auf dem Wochentag möchte ich die Daten der Spalte "Received" für die nächsten 4 bis 11 Tage aggregieren, beschränkt auf die entsprechende SKU.

Die Ausgabe könnte wie folgt aussehen:

Date   SKU received Weekday Order 
2017-05-29 sku1 0   0   8 
2017-05-30 sku1 0   1   0 
2017-05-31 sku1 0   2   0 
2017-06-01 sku1 0   3   0 
2017-06-02 sku1 6   4   0 
2017-06-03 sku1 2   5   0 
2017-05-29 sku2 4   0   24 
2017-05-30 sku2 4   1   0 
2017-05-31 sku2 0   2   0 
2017-06-01 sku2 0   3   0 
2017-06-02 sku2 0   4   0 
2017-06-03 sku2 24   5   0 

Hier ist der Code, den ich versuchte:

import pandas as pd 

# 0 is Monday, 1 is Tuesday, etc 
df["Weekday"] = df["Date"].dt.dayofweek 

# create new column for the orders 
df["Order"] = 0 

min_days = 4 
max_days = min_days + 7 

for i in range(len(df)): 
    if df.loc[i, "Weekday"] == 0: 
     df.loc[i, "Order"] = df.loc[(df.Date >= df.loc[i, "Date"] + pd.to_timedelta(min_days, unit="D")) & 
            (df.Date < df.loc[i, "Date"] + pd.to_timedelta(max_days, unit="D")) & 
            (df.SKU == df.loc[i, "SKU"]), "received"].sum() 

Es scheint, die Arbeit zu tun, aber in einer langsamen Art und Weise. Vielleicht kann mir jemand helfen, einen Python/Pandas-Ansatz zu finden, um Rechenzeit zu sparen.

Danke für Ihre Hilfe.

Antwort

1

Hier ist eine mögliche Lösung, die pandas groupby und transform verwendet.

Erste Idee ist, dass Sie die Anzahl zwischen zwei Tagen erreichen können, indem Sie die Differenz der rollenden Summen nehmen. Beachten Sie auch den Trick, die Bestellung zweimal ([::-1]) zweimal umzukehren, um eine rollende Summe zu erhalten, die Tage in der Zukunft auswählt.

def count_between(ts, min_days, max_days): 
    return ts[::-1].pipe(lambda y: y.rolling(max_days,1).sum() - y.rolling(min_days-1,1).sum())[::-1] 

Diese Funktion würde Ihnen Ergebnisse für jeden Tag, so dass Sie die Ergebnisse montags beschränken nur alle anderen Einträge auf 0 setzen (mit [.where][1]).

Nach Date als Index einstellen, können Sie folgendes tun:

order = df.groupby('SKU')\ 
      .transform(lambda x: count_between(x, min_days, max_days)\ 
           .where(lambda y: y.index.dayofweek==0, other = 0)) 
order.columns = ['Order'] 

Dies gibt das erwartete Ergebnis:

pd.concat([df, order], axis = 1) 
Out[319]: 
      SKU received Order 
Date        
2017-05-29 sku1   0 8.0 
2017-05-30 sku1   0 0.0 
2017-05-31 sku1   0 0.0 
2017-06-01 sku1   0 0.0 
2017-06-02 sku1   6 0.0 
2017-06-03 sku1   2 0.0 
2017-05-29 sku2   4 24.0 
2017-05-30 sku2   4 0.0 
2017-05-31 sku2   0 0.0 
2017-06-01 sku2   0 0.0 
2017-06-02 sku2   0 0.0 
2017-06-03 sku2  24 0.0 
+0

dank @FLab. Mein 'df' ist in der Tat ein bisschen größer und hat mehr Spalten,' Date' ist nicht der Index, weshalb ich Schwierigkeiten habe, den Code 'y.index.dayofweek == 0' auszuführen. – Axel

+0

Anpassung des Codes an 'count_between (x.received, min_days, max_days)' und '.where (lambda y: y.Date.dayofweek == 0' hilft nicht. Fehle ich etwas? – Axel

+0

Oh, ja, sollte haben erwähnt, dass ich Datum als Index gesetzt habe.Kann man nicht auf einer Teilmenge des Datenrahmens operieren, die aussieht wie das gemeldete Beispiel? In der Zwischenzeit denke ich an eine Lösung – FLab

Verwandte Themen