pandas: Problem mit pivot_table und zwei Spalten für die Darstellung

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Benutzeravatar
noisefloor
User
Beiträge: 4257
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

die folgenden Daten sollen nach Jahr, Monat und Produktgruppe gruppiert und aufsummiert werden. Die Produktgruppe stellen die Buchstaben der Artikelnummer dar.

Beispieldaten (sind im Original in einer Excel-Datei):

Code: Alles auswählen

No_SalesLine	ShipmentDate_SalesLine	SalesOrderAmount
AL000660	01.04.26	10926,9
S_02	01.04.26	95
AL000113	01.04.26	20582,4
S_02	01.04.26	190
AL000020	01.06.26	22521,6
AL000112	01.10.26	19206
AL000632	01.10.26	19756,44
S_02	01.10.26	418
AL000113	01.12.26	22640,64
S_02	01.12.26	209
AL000679	02.02.26	5961,6
S_02	02.02.26	57
ZR000020	02.02.26	3907,2
FS001862	02.07.26	56595
S_02	02.07.26	1540
ANLB001015	03.02.26	7159,15
S_02	03.02.26	25
ANLB001252	03.03.26	29366,31
S_02	03.03.26	686,93
AL000632	03.03.26	8906,88
S_02	03.03.26	76
S_01	03.03.26	600
AL000359	03.03.26	18598,72
AL000786	03.03.26	11535,66
S_02	03.03.26	209
S_01	03.03.26	1650
NULL	NULL	NULL
NULL	NULL	NULL
Der folgende Code macht das auch:

Code: Alles auswählen

import pandas as pd

OPEN_ORDERS_FILE = 'daten_beispiel.xlsx'

df = pd.read_excel(OPEN_ORDERS_FILE, header=0,
                   usecols=['No_SalesLine', 'ShipmentDate_SalesLine',
                             'SalesOrderAmount'],
                   dtype={'SalesOrderAmount': float})

#Aufräumen des Data Frames:
# 1. alle Zeilen entfernen, wie alle Werte NaN sind
# 2. alle Zeilen entfernen, die einen MU-Artikel enthalten, weil der
#    Betrag hier Null (0) sein muss
# 3. Artikelnummer in String umwandeln
# 4. Datum ins ISO8601 Format konvertieren
# 5. Produktgruppe basierend auf der Artikelnummer hinzufügen
df = df.dropna(how='all')
indices_to_drop = df[df['No_SalesLine'].str.startswith('MU') == True].index
df = df.drop(indices_to_drop)
df = df.astype({'No_SalesLine': 'string'})
df['ShipmentDate_SalesLine'] = pd.to_datetime(df['ShipmentDate_SalesLine'], format='%d.%m.%y', yearfirst=True)
df['ItemGroup'] = df['No_SalesLine'].str.extract(r'([A-Z]{1,4})')
df_by_year_and_month = df.groupby([df['ShipmentDate_SalesLine'].dt.year, df['ShipmentDate_SalesLine'].dt.month, 'ItemGroup']).agg({'SalesOrderAmount':'sum'})
print('Umsatzvorschau, Gesamtübersicht, Summe in Euro')
print('----------------------------------------------')
print(df_by_year_and_month.to_string())
print('\n\n`')
Mir wäre nur eine Darstellung lieber, wo die Produktgruppe in den Zeilen steht und die Spalten nach Jahr und Monat gruppiert sind. Also so:

Code: Alles auswählen

	2026						
Zeilenbeschriftungen	2	3	4	6	7	10	12
AL	5961,6	39041,26	31509,3	22521,6		38962,44	22640,64
ANLB	7159,15	29366,31					
FS					56595		
S	82	3221,93	285		1540	418	209
ZR	3907,2						
Gesamtergebnis	17109,95	71629,5	31794,3	22521,6	58135	39380,44	22849,64

Geht theoretisch auch in Pandas mit einer Pivot Tabelle - kriege ich praktisch aber nicht hin.

Die Zeile:

Code: Alles auswählen

table = pd.pivot_table(df, values='SalesOrderAmount', index=['ItemGroup'],
                       columns=[df['ShipmentDate_SalesLine'].dt.year, df['ShipmentDate_SalesLine'].dt.month], 
                       aggfunc='sum')
wirft den Fehler:

Code: Alles auswählen

ValueError: The name ShipmentDate_SalesLine occurs multiple times, use a level number
Nur verstehe ich nicht, was man an `columns` übergeben muss, damit die Darstellung so ist wie gewünscht. Also ich verstehe nicht, wie und wo man einen Level übergeben könnte und diverse Experiment, `pd.Grouper` Objekte zu übergeben, waren auch erfolglos.
Antworten