Laufzeit problem mit pandas.Dataframes

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Lukasn
User
Beiträge: 1
Registriert: Donnerstag 9. Mai 2024, 16:11

Hallo zusammen. Das hier ist mein erster Beitrag, also evtl. werde ich wichtige Informationen zu meinem Problem vergessen :D

Ich habe zwei Dataframes:
1. Mengenrestriktion_groups sieht folgendermaßen aus:
  • Produktgruppe1 Produktgruppe2 Produktgruppe3 ...
    Montag_Min 3264 768 0 ...
    Montag_Max 3456 1728 192 ...
    Dienstag_Min 3264 768 0 ...
    Dienstag_Max 3456 1728 192 ...
    Mittwoch_Min 3264 768 0 ...
    Mittwoch_Max 3456 1728 192 ...
    Donnerstag_Min 3264 768 0 ...
    Donnerstag_Max 3456 1728 192 ...
    Freitag_Min 3264 768 0 ...
    Freitag_Max 3456 1728 192 ...

    Index = Min/Max Limits der Wochentage
    columns sind die Produktgruppen
    data sind die anzahl der erlaubten Produkte jeder Gruppe, die an den entsprechenden Tagen mindestens/maximal produziert werden sollen
2. Mengenrestriktion_products:
  • Produktname1 Produktname2 Produktname3 ...
    Produktgruppe1 0 1 1 ...
    Produktgruppe2 1 0 0 ...
    Produktgruppe3 0 1 0 ...
    ... ... ...

    [16 rows x 717 columns]
    Index = Die Produktgruppen (entsprechen auch den Produktgruppen aus Mengenrestriktion_groups)
    columns = Name von einzelnen Produkten
    values = 1, wenn Produkt in Produktgruppe ist, sonst 0
Nun habe ich eine Reihe von Produkten (versehen mit einem Tag, an dem sie produziert werden) . Ich möchte überprüfen, ob die Anzahl dieser Produkte die maximalen oder minimalen Mengenrestriktionen in Mengenrestriktionen_groups verletzt.
Dazu schaue ich zuerst nach unter welche Produktgruppen das Produkt fällt (Mithilfe Mengenrestriktionen_products). Das summiere ich für jedes Produkt und jede Produktgruppe auf und schaue dann ob der Wert der Produktgruppen innerhalb der Limits aus Mengenrestriktionen_groups liegt.
Dazu hier mein Code:

Code: Alles auswählen

   def adjust_to_minmax_frame(self, products,dates,  df_mengenrestiktion_products:pd.DataFrame):
        products_adjusted = []
        dates_adjusted = []
        for product,day in zip(products, dates):
            if product in df_mengenrestiktion_products.columns:
                #es werden immer 48 Produkte produziert
                product_value = df_mengenrestiktion_products[product] * 48
                #doppeltes hinzufügen der Anzahl, da es mit min  und mit max restriktion verrechnet werden soll
                products_adjusted.extend([product_value, product_value])
                dates_adjusted.extend([day.strftime('%A')+"_Min", day.strftime('%A')+"_Max"])
       return products_adjusted, dates_adjusted    
    
    def create_schedule_dataframe(self, Mengenrestriktion_groups: pd.DataFrame, Mengenrestriktion_product: pd.DataFrame):
        #erstellen von DataFrame um es anschließend mit Anzahl der produzierten Produkte der Produktgruppen zu füllen   
        df = pd.DataFrame(0, index = Mengenrestriktion_groups.index, columns = Mengenrestriktion_groups.columns)
        #Liste der Produkte
        products = self.get_schedule()
        #Liste der Daten an welchen Produkte produziert werden
        dates = self.get_dates()
        Mengenrestriktion_product = Mengenrestriktion_product.reindex(index=Mengenrestriktion_groups.columns.to_list())
        adjusted_products, adjusted_dates = self.adjust_to_minmax_frame(products, dates, Mengenrestriktion_product)
        for product,date in zip(adjusted_products, adjusted_dates): #df an der Stelle des Tags += Anzahl der Produkte der einzelnen Produktgruppen
            df.loc[date] += product.values
        return df
    
   #Hier wird die tatsächlich Produzierte Anzahl der einzelnen Produktgruppen von den Limit abgezogen um zu sehen, ob Limits verletzt werden. 
  produced_amount = create_schedule_dataframe(self.df_mengenrestriktionen_groups, self.df_mengenrestriktionen_products)
  restriction = df_mengenrestriktionen_groups - produced_amount 

Wie ihr euch vermutlich schon vorstellen könnt, ist dieser Code sehr langsam. Die Liste der Produkte ist ca 1600 items lang, Die dataframes sind deutilch größer, als hier dargestellt und die Berechung läuft sehr oft ab (ca. 130k iterationen). Dementsprechen wichtig ist es, dass ganze schnell berechnen zu können.

Ich wäre sehr dankbar für Vorschläge von etwas erfahreneren Programmieren, als mir selbst.

Viele Grüße und vielen Dank,
Lukas
Sven_TKLOOP
User
Beiträge: 12
Registriert: Freitag 16. August 2024, 14:10

Dein Code iteriert über die Produkte und manipuliert dabei den DataFrame direkt in einer Schleife. Das führt zu wiederholten Operationen auf großen Datenstrukturen und ist daher extrem langsam.
Du fügst jedes Produkt zweimal zu Liste hinzu was zu doppelt so vielen Iterationen führt und das macht sich dann halt bemerkbar.
Wenn du versuchst, die gesamte Verarbeitung in einem Schritt über die DataFrames abzuwickeln, sollte sich die Performance auch deutlich verbessern
Du könntest alle Produktinformationen in einem DataFrame speichern und dann nach den Tagen gruppieren. Damit kannst du die Anzahl der produzierten Einheiten pro Produkt direkt zu berechnen, ohne durch jede einzelne Zeile iterieren zu müssen.
Mit Matrixoperationen könntest du die Zuordnung der Produktgruppen auch effizienter machen.
Antworten