Skip to content

Pandas-Pivot-Tabelle: Daten wie in Excel zusammenfassen und umformen (Guide)

Updated on

Jede Analystin und jeder Analyst, die/der mit Excel gearbeitet hat, kennt Pivot-Tabellen. Du ziehst ein Feld in den Zeilenbereich, ein anderes in den Spaltenbereich, wählst eine Zusammenfassungsfunktion – und aus einem dichten Spreadsheet voller Rohtransaktionen wird eine saubere Übersicht: Summen nach Kategorie, Durchschnittswerte nach Region oder Anzahlen pro Monat. Jetzt willst du das Gleiche in Python machen, aber verschachtelte groupby-Aufrufe mit unstack wirken umständlich und sind schwer zu lesen.

Die eigentliche Frustration kommt, wenn deine Daten mehrere Gruppierungsebenen haben, du Zwischensummen brauchst oder mehrere Aggregationsfunktionen gleichzeitig auf verschiedene Spalten anwenden willst. groupby, agg und unstack zu verketten führt schnell zu fragilem Code, der bricht, sobald sich die Datenform ändert.

Die Funktion pandas pivot_table bringt die volle Power von Excel-Pivot-Tabellen nach Python – mit einer sauberen, deklarativen API. Ein einziger Funktionsaufruf übernimmt Gruppierung, Aggregation, mehrstufige Indizes, Zwischensummen und den Umgang mit fehlenden Werten. Dieser Guide erklärt jeden Parameter, zeigt praxisnahe Beispiele und vergleicht pivot_table mit groupby, pivot und crosstab, damit du genau weißt, welches Werkzeug du wann einsetzen solltest.

📚

Was pd.pivot_table() macht

pd.pivot_table() erstellt aus einem DataFrame eine Spreadsheet-ähnliche Zusammenfassungstabelle. Du legst fest, welche Spalten als Zeilenbeschriftungen (index) dienen, welche als Spaltenüberschriften, welche Werte aggregiert werden sollen und welche Aggregationsfunktion angewendet wird. Das Ergebnis ist ein neuer DataFrame, in dem jede Zelle eine Kennzahl (Summary Statistic) enthält.

Hier ein einfaches Vorher-nachher:

Rohdaten:

regionproductrevenue
NorthWidget1200
NorthGadget800
SouthWidget1500
SouthGadget950
NorthWidget1400
SouthWidget1600

Pivot-Tabelle (Summe von revenue nach region und product):

regionGadgetWidget
North8002600
South9503100

Jede Zelle enthält die Summe des Umsatzes für diese Kombination aus Region und Produkt.

pd.pivot_table() Syntax und Parameter

pd.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean',
               fill_value=None, margins=False, dropna=True, margins_name='All',
               observed=False, sort=True)

Parameter-Referenz

ParameterBeschreibungStandard
dataDer DataFrame, der zusammengefasst werden sollErforderlich
valuesSpalte(n), die aggregiert werden sollenNone (alle numerischen Spalten)
indexSpalte(n) als ZeilenlabelsNone
columnsSpalte(n) als SpaltenüberschriftenNone
aggfuncAggregationsfunktion(en): 'mean', 'sum', 'count', 'min', 'max' oder eine Funktion/dict/list'mean'
fill_valueWert zum Ersetzen von NaN im ErgebnisNone
marginsZeilen-/Spaltentotale hinzufügen (Zwischensummen)False
margins_nameName für die Totals-Zeile/Spalte'All'
dropnaSpalten ausschließen, deren Einträge vollständig NaN sindTrue
observedBei kategorialen Spalten nur beobachtete Kategorien anzeigenFalse
sortErgebnis sortierenTrue

Beispieldaten für alle Beispiele

Jedes Beispiel unten verwendet dieses Sales-Dataset:

import pandas as pd
import numpy as np
 
sales = pd.DataFrame({
    'date': pd.to_datetime(['2025-01-15', '2025-01-20', '2025-02-10', '2025-02-18',
                            '2025-01-12', '2025-02-22', '2025-01-25', '2025-02-14',
                            '2025-01-30', '2025-02-05', '2025-01-18', '2025-02-28']),
    'region': ['North', 'North', 'North', 'North', 'South', 'South',
               'South', 'South', 'East', 'East', 'East', 'East'],
    'product': ['Widget', 'Gadget', 'Widget', 'Gadget',
                'Widget', 'Gadget', 'Widget', 'Gadget',
                'Widget', 'Gadget', 'Widget', 'Gadget'],
    'salesperson': ['Alice', 'Alice', 'Bob', 'Bob',
                    'Charlie', 'Charlie', 'Diana', 'Diana',
                    'Eve', 'Eve', 'Frank', 'Frank'],
    'revenue': [1200, 800, 1400, 850, 1500, 950, 1100, 780, 1300, 900, 1250, 870],
    'units': [10, 8, 12, 9, 15, 10, 11, 8, 13, 9, 12, 9]
})
 
print(sales)

Einfache Pivot-Tabelle: Summe des Umsatzes nach Region

table = pd.pivot_table(sales, values='revenue', index='region', aggfunc='sum')
print(table)

Output:

        revenue
region
East       4320
North      4250
South      4330

Das ist äquivalent zu sales.groupby('region')['revenue'].sum(), liefert aber einen DataFrame statt einer Series.

Spaltenüberschriften hinzufügen

Füge den Parameter columns hinzu, um die Zusammenfassung nach einer zweiten Variable aufzuschlüsseln:

table = pd.pivot_table(sales, values='revenue', index='region',
                       columns='product', aggfunc='sum')
print(table)

Output:

product  Gadget  Widget
region
East       1770    2550
North      1650    2600
South      1730    2600

Jetzt zeigt jede Zelle den Gesamtumsatz für ein bestimmtes Region-Produkt-Paar.

Mehrere Aggregationsfunktionen

Übergebe eine Liste von Funktionen an aggfunc, um mehrere Kennzahlen auf einmal zu berechnen:

table = pd.pivot_table(sales, values='revenue', index='region',
                       columns='product', aggfunc=['sum', 'mean', 'count'])
print(table)

Output:

          sum          mean                count
product Gadget Widget Gadget  Widget      Gadget Widget
region
East      1770   2550  885.0  1275.0           2      2
North     1650   2600  825.0  1300.0           2      2
South     1730   2600  865.0  1300.0           2      2

Das Ergebnis hat einen MultiIndex in den Spalten: oben die Aggregationsfunktion, darunter das Produkt.

Unterschiedliche Aggregationsfunktionen pro Spalte

Nutze ein Dictionary für aggfunc, um je Werte-Spalte unterschiedliche Funktionen anzuwenden:

table = pd.pivot_table(sales, values=['revenue', 'units'], index='region',
                       columns='product',
                       aggfunc={'revenue': 'sum', 'units': 'mean'})
print(table)

Output:

       revenue         units
product Gadget Widget Gadget Widget
region
East      1770   2550    9.0   12.5
North     1650   2600    8.5   11.0
South     1730   2600    9.0   13.0

Der Umsatz wird summiert, während units gemittelt werden – genau wie in einer Excel-Pivot-Tabelle mit unterschiedlichen Zusammenfassungsfunktionen pro Feld.

Zwischensummen mit margins hinzufügen

Der Parameter margins fügt eine Zeile und eine Spalte mit den Gesamtsummen hinzu:

table = pd.pivot_table(sales, values='revenue', index='region',
                       columns='product', aggfunc='sum', margins=True)
print(table)

Output:

product  Gadget  Widget    All
region
East       1770    2550   4320
North      1650    2600   4250
South      1730    2600   4330
All        5150    7750  12900

Die All-Zeile zeigt den Gesamtumsatz pro Produkt. Die All-Spalte zeigt den Gesamtumsatz pro Region. Die Zelle unten rechts ist die Gesamtsumme.

Du kannst das Label mit margins_name anpassen:

table = pd.pivot_table(sales, values='revenue', index='region',
                       columns='product', aggfunc='sum',
                       margins=True, margins_name='Total')
print(table)

Fehlende Werte mit fill_value behandeln

Wenn bestimmte Kombinationen in deinen Daten nicht vorkommen, enthält die Pivot-Tabelle NaN. Mit fill_value ersetzt du sie:

# Remove one row to create a missing combination
sales_missing = sales.drop(index=0)
 
table = pd.pivot_table(sales_missing, values='revenue', index='region',
                       columns='product', aggfunc='sum', fill_value=0)
print(table)

Das ersetzt NaN durch 0, was übersichtlicher ist und Probleme in nachgelagerten Berechnungen vermeidet.

Multi-Level Index (Zeilen-Gruppierung)

Übergebe eine Liste von Spalten an index, um hierarchische Zeilenlabels zu erstellen:

table = pd.pivot_table(sales, values='revenue',
                       index=['region', 'salesperson'],
                       columns='product', aggfunc='sum')
print(table)

Output:

product                Gadget  Widget
region salesperson
East   Eve              900.0  1300.0
       Frank            870.0  1250.0
North  Alice            800.0  1200.0
       Bob              850.0  1400.0
South  Charlie          950.0  1500.0
       Diana            780.0  1100.0

Jede Verkäuferperson ist unter ihrer Region verschachtelt – ideal für eine Drill-down-Sicht auf die Daten.

Multi-Level Spalten

Analog kannst du bei columns eine Liste für hierarchische Spaltenüberschriften übergeben:

sales['month'] = sales['date'].dt.month_name()
 
table = pd.pivot_table(sales, values='revenue', index='region',
                       columns=['product', 'month'], aggfunc='sum', fill_value=0)
print(table)

Das erzeugt einen zweistufigen Spaltenheader: oben product, darunter month.

Eigene Aggregationsfunktionen verwenden

Du kannst jede Callable an aggfunc übergeben – inklusive Lambda-Funktionen und NumPy-Funktionen:

# Range (max - min) of revenue by region
table = pd.pivot_table(sales, values='revenue', index='region',
                       columns='product', aggfunc=lambda x: x.max() - x.min())
print(table)

Output:

product  Gadget  Widget
region
East         30      50
North        50     200
South       170     400

Weitere nützliche Custom-Aggregationen:

# Coefficient of variation
table = pd.pivot_table(sales, values='revenue', index='region',
                       aggfunc=lambda x: x.std() / x.mean() * 100)

Praxisbeispiel: Analyse von Studentennoten

students = pd.DataFrame({
    'student': ['Alice', 'Alice', 'Alice', 'Bob', 'Bob', 'Bob',
                'Charlie', 'Charlie', 'Charlie', 'Diana', 'Diana', 'Diana'],
    'subject': ['Math', 'Science', 'English'] * 4,
    'semester': ['Fall', 'Fall', 'Fall', 'Fall', 'Fall', 'Fall',
                 'Spring', 'Spring', 'Spring', 'Spring', 'Spring', 'Spring'],
    'score': [92, 88, 95, 78, 85, 72, 90, 93, 88, 85, 79, 91]
})
 
# Average score by subject and semester
table = pd.pivot_table(students, values='score', index='subject',
                       columns='semester', aggfunc='mean', margins=True)
print(table.round(1))

Output:

semester   Fall  Spring   All
subject
English    83.5    89.5  86.5
Math       85.0    87.5  86.2
Science    86.5    86.0  86.2
All        85.0    87.7  86.3

Das zeigt sofort, dass die Durchschnittswerte im Spring-Semester insgesamt etwas höher sind – mit der größten Verbesserung in English.

Praxisbeispiel: Monatlicher Sales-Report

# Create a monthly sales summary
sales['month'] = sales['date'].dt.strftime('%Y-%m')
 
report = pd.pivot_table(sales, values=['revenue', 'units'],
                        index='region', columns='month',
                        aggfunc={'revenue': 'sum', 'units': 'sum'},
                        margins=True, fill_value=0)
print(report)

Das erzeugt denselben monatlichen Summary-Report, den du auch in Excel bauen würdest – inklusive Totals pro Region und Monat.

pivot_table vs pivot vs groupby vs crosstab

Diese vier Funktionen überschneiden sich in ihren Möglichkeiten, aber jede hat einen klaren Use Case:

Featurepivot_table()pivot()groupby()crosstab()
AggregationJa (jede Funktion)Nein (wirft Fehler bei Duplikaten)Ja (jede Funktion)Ja (begrenzt)
Handles duplicatesJa, über aggfuncNeinJaJa
Subtotals (margins)JaNeinNein (manuell)Ja
Fill missing valuesJa (fill_value)NeinNeinJa (fill_value)
InputDataFrameDataFrameDataFrameSeries/arrays
OutputDataFrameDataFrameDataFrame/SeriesDataFrame
Multi-level indexJaJaJaJa
Best forDaten mit Aggregation zusammenfassenEindeutige Key-Value-Daten umformenFlexible gruppierte AnalysenHäufigkeitstabellen
Default functionmeanN/AN/Acount

Wann du was verwendest

Nutze pivot_table(), wenn du Excel-ähnliche Zusammenfassungen mit Aggregation, Totals/Zwischensummen oder mehreren Aggregationsfunktionen brauchst. Das ist die leistungsstärkste und lesbarste Option für Summary-Tabellen.

Nutze pivot(), wenn deine Daten eindeutige Kombinationen aus index- und column-Werten haben und du nur umformen (reshape) willst – ohne Aggregation. Es ist schneller als pivot_table(), weil der Aggregationsschritt entfällt.

Nutze groupby(), wenn du gruppierte Berechnungen brauchst, aber kein Wide-Format als Ergebnis. groupby liefert standardmäßig Long-Format. Ein pivot_table-ähnliches Ergebnis geht mit groupby().unstack(), aber pivot_table ist meist besser lesbar.

Nutze crosstab(), wenn du Häufigkeitstabellen oder Kreuztabellen (Cross-Tabulations) kategorialer Variablen berechnest. crosstab() akzeptiert Series oder Arrays direkt (nicht nur DataFrames) und zählt standardmäßig.

Äquivalenz-Beispiel

Diese drei Zeilen erzeugen dasselbe Ergebnis:

# pivot_table approach
result1 = pd.pivot_table(sales, values='revenue', index='region',
                         columns='product', aggfunc='sum')
 
# groupby + unstack approach
result2 = sales.groupby(['region', 'product'])['revenue'].sum().unstack()
 
# Both produce the same table
print(result1.equals(result2))  # True

Die pivot_table-Variante ist besser lesbar – besonders, wenn du margins, fill values oder mehrere Aggregationsfunktionen hinzufügst.

MultiIndex-Spalten abflachen (Flattening)

Wenn du eine Pivot-Tabelle mit mehreren Aggregationsfunktionen erzeugst, erhältst du oft MultiIndex-Spalten, mit denen man schwer arbeiten kann:

table = pd.pivot_table(sales, values='revenue', index='region',
                       columns='product', aggfunc=['sum', 'mean'])
 
# Flatten the column MultiIndex
table.columns = ['_'.join(col).strip() for col in table.columns.values]
print(table)

Output:

        sum_Gadget  sum_Widget  mean_Gadget  mean_Widget
region
East          1770        2550        885.0       1275.0
North         1650        2600        825.0       1300.0
South         1730        2600        865.0       1300.0

Jetzt sind die Spalten flache Strings und lassen sich leichter referenzieren.

Pivot-Tabellen sortieren und filtern

Pivot-Tabellen sind normale DataFrames – du kannst sie also sortieren und filtern:

table = pd.pivot_table(sales, values='revenue', index='region',
                       columns='product', aggfunc='sum', margins=True)
 
# Sort by total revenue (All column), descending
sorted_table = table.sort_values('All', ascending=False)
print(sorted_table)
 
# Filter to show only regions with Widget revenue > 2500
filtered = table[table['Widget'] > 2500]
print(filtered)

Pivot-Tabellen exportieren

Speichere deine Pivot-Tabelle nach Excel (wo Stakeholder sie erwarten) oder als CSV:

table = pd.pivot_table(sales, values='revenue', index='region',
                       columns='product', aggfunc='sum', margins=True)
 
# Export to Excel
table.to_excel('sales_pivot.xlsx', sheet_name='Revenue Summary')
 
# Export to CSV
table.to_csv('sales_pivot.csv')

Performance-Tipps

pivot_table() ruft intern groupby auf, daher ist die Performance ähnlich. Für große Datensätze:

Dataset SizeExpected Time
100K rows, 2 group cols~5 ms
1M rows, 2 group cols~50 ms
10M rows, 3 group cols~500 ms

Optimierungsstrategien:

  1. Daten vor dem Pivot reduzieren – filtere Zeilen und wähle nur die benötigten Spalten aus, bevor du pivot_table() aufrufst.
  2. Categorical dtypes verwenden – wandle String-Spalten in den category dtype um, um schneller zu gruppieren.
  3. Lambda aggfuncs vermeiden – eingebaute String-Namen ('sum', 'mean') nutzen optimierten C-Code. Lambda-Funktionen fallen auf langsamere Python-Loops zurück.
# Faster: use categorical dtypes
sales['region'] = sales['region'].astype('category')
sales['product'] = sales['product'].astype('category')
 
# Faster: use string name instead of lambda
table = pd.pivot_table(sales, values='revenue', index='region',
                       columns='product', aggfunc='sum')  # 'sum' is optimized

Pivot-Tabellen mit PyGWalker visualisieren

Während pd.pivot_table() großartig für numerische Zusammenfassungen ist, willst du manchmal Muster in deinen Daten interaktiv visualisieren. PyGWalker (opens in a new tab) ist eine Open-Source-Python-Library, mit der du Pivot-Tabellen, Balkendiagramme, Heatmaps und mehr über ein visuelles Drag-and-drop-Interface erstellen kannst – nach dem initialen Setup ohne weiteren Code.

import pandas as pd
import pygwalker as pyg
 
sales = pd.DataFrame({
    'region': ['North', 'North', 'South', 'South', 'East', 'East'] * 2,
    'product': ['Widget', 'Gadget'] * 6,
    'revenue': [1200, 800, 1500, 950, 1300, 900, 1400, 850, 1100, 780, 1250, 870],
    'units': [10, 8, 15, 10, 13, 9, 12, 9, 11, 8, 12, 9]
})
 
# Launch interactive pivot table and visualization
walker = pyg.walk(sales)

PyGWalker bietet dir ein Tableau-ähnliches Interface, in dem du region auf Rows, product auf Columns und revenue auf Values ziehen kannst, um visuell eine Pivot-Tabelle zu erstellen. Du kannst sofort zwischen Tabellen- und Chart-Ansicht wechseln, verschiedene Aggregationsfunktionen ausprobieren und das Ergebnis exportieren – ohne zusätzlichen Code zu schreiben.

Probiere PyGWalker in Google Colab (opens in a new tab), Kaggle (opens in a new tab), oder installiere es mit pip install pygwalker.

FAQ

Was ist der Unterschied zwischen pivot und pivot_table in pandas?

pivot() formt Daten ohne Aggregation um – es erfordert eindeutige Kombinationen aus Index- und Spaltenwerten und wirft einen Fehler, wenn Duplikate existieren. pivot_table() kann mit Duplikaten umgehen, indem es sie mit einer Funktion wie sum oder mean aggregiert. Verwende pivot() für einfaches Reshaping und pivot_table(), wenn du Aggregation oder Totals/Zwischensummen brauchst.

Wie füge ich Totals (margins) zu einer pandas Pivot-Tabelle hinzu?

Setze margins=True im pivot_table()-Aufruf: pd.pivot_table(df, values='revenue', index='region', columns='product', aggfunc='sum', margins=True). Das fügt eine All-Zeile und -Spalte mit Zwischensummen hinzu. Passe das Label mit margins_name='Total' an.

Kann ich mehrere Aggregationsfunktionen in einer Pivot-Tabelle verwenden?

Ja. Übergib eine Liste an aggfunc: aggfunc=['sum', 'mean', 'count']. Das erzeugt einen MultiIndex-Spaltenheader mit einer Ebene für die Funktion und einer Ebene für die Values-Spalten. Du kannst auch ein Dictionary übergeben, um je Spalte unterschiedliche Funktionen zu nutzen: aggfunc={'revenue': 'sum', 'units': 'mean'}.

Worin unterscheidet sich pivot_table von groupby in pandas?

Beide aggregieren Daten, aber pivot_table() erzeugt ein Wide-Format-Ergebnis (mit Spaltenüberschriften aus einer der Gruppierungsvariablen), während groupby() standardmäßig Long-Format liefert. pivot_table() unterstützt außerdem margins (Zwischensummen) und fill values nativ. Intern verwendet pivot_table() groupby().

Wie gehe ich mit NaN-Werten in einer Pivot-Tabelle um?

Verwende den Parameter fill_value, um NaN durch einen bestimmten Wert zu ersetzen: pd.pivot_table(df, ..., fill_value=0). Der Parameter dropna=True (Standard) schließt Spalten aus, deren Einträge vollständig NaN sind.

Kann ich eine Pivot-Tabelle mit Prozentwerten erstellen?

Ja. Erstelle zuerst die Pivot-Tabelle mit Counts oder Summen und teile dann durch die Gesamtsumme. Alternativ kannst du bei pd.crosstab() normalize für prozentbasierte Kreuztabellen verwenden. Für Pivot-Tabellen berechnest du Prozente manuell: table = table.div(table.sum(axis=1), axis=0) * 100.

Fazit

Die pandas-Funktion pivot_table() ist das vielseitigste Werkzeug, um Summary-Tabellen in Python zu erstellen. Die wichtigsten Punkte:

  • Nutze values, index und columns, um festzulegen, was zusammengefasst wird, wie Zeilen gruppiert werden und wie Spalten gruppiert werden.
  • Nutze aggfunc, um die Aggregationsfunktion festzulegen. Übergib eine Liste für mehrere Funktionen oder ein Dictionary für Funktionen pro Spalte.
  • Nutze margins=True, um Zwischensummen hinzuzufügen – das Pendant zu „Grand Total“ in Excel.
  • Nutze fill_value, um fehlende Kombinationen durch einen Standardwert zu ersetzen (typischerweise 0).
  • Bevorzuge pivot_table() gegenüber groupby().unstack() wegen der Lesbarkeit, besonders wenn du margins oder fill values brauchst.
  • Bevorzuge pivot() gegenüber pivot_table(), wenn deine Daten eindeutige Key-Kombinationen haben und du keine Aggregation brauchst.
  • Bevorzuge crosstab() für einfache Häufigkeitstabellen kategorialer Variablen.

Für die interaktive Exploration deiner Pivot-Tabellen bietet PyGWalker (opens in a new tab) ein visuelles Drag-and-drop-Interface, das das Excel-Pivot-Tabellen-Erlebnis in Jupyter Notebook nachbildet.

📚