Pivot-Tabellen und Kreuztabellen#

Eine Pivot-Tabelle ist ein Werkzeug zur Datenzusammenfassung, das häufig in Tabellenkalkulationsprogrammen und anderer Datenanalysesoftware zu finden ist. Sie fasst eine Tabelle mit Daten nach einem oder mehreren Schlüsseln zusammen und ordnet die Daten in einem Rechteck an, wobei einige der Gruppenschlüssel entlang der Zeilen und einige entlang der Spalten angeordnet sind. Pivot-Tabellen in Python mit pandas werden durch die groupby-Funktion in Kombination mit Umformungsoperationen unter Verwendung hierarchischer Indizierung ermöglicht. DataFrame hat eine pivot_table-Methode, und es gibt auch eine Top-Level-Funktion pandas.pivot_table. pivot_table bietet nicht nur eine bequeme Schnittstelle zu groupby, sondern kann auch Teilsummen (margins) hinzufügen.

Nehmen wir an, wir wollten eine Tabelle mit Gruppenmittelwerten (der Standardaggregationstyp von pivot_table) berechnen, die nach Titel und Sprache in den Zeilen geordnet ist:

[1]:
import numpy as np
import pandas as pd
[2]:
df = pd.DataFrame(
    {
        "2021-12": [30134, 6073, 4873, None, 427, 95],
        "2022-01": [33295, 7716, 3930, None, 276, 226],
        "2022-02": [19651, 6547, 2573, None, 525, 157],
    },
    index=[
        [
            "Jupyter Tutorial",
            "Jupyter Tutorial",
            "PyViz Tutorial",
            "PyViz Tutorial",
            "Python Basics",
            "Python Basics",
        ],
        ["de", "en", "de", None, "de", "en"],
    ],
)

df.index.names = ["Title", "Language"]
[3]:
df.pivot_table(index=["Title", "Language"])
[3]:
2021-12 2022-01 2022-02
Title Language
Jupyter Tutorial de 30134.0 33295.0 19651.0
en 6073.0 7716.0 6547.0
PyViz Tutorial de 4873.0 3930.0 2573.0
Python Basics de 427.0 276.0 525.0
en 95.0 226.0 157.0

Das hätte man auch direkt mit groupby machen können.

Nehmen wir nun an, wir wollen den Durchschnitt jeden Monats nehmen und zusätzlich nach Title gruppieren. Ich werde Title und Language in die Tabellenspalten und die Monate in die Zeilen setzen:

[4]:
df.pivot_table(columns=["Title", "Language"])
[4]:
Title Jupyter Tutorial PyViz Tutorial Python Basics
Language de en de de en
2021-12 30134.0 6073.0 4873.0 427.0 95.0
2022-01 33295.0 7716.0 3930.0 276.0 226.0
2022-02 19651.0 6547.0 2573.0 525.0 157.0

Wir können diese Tabelle um Teilsummen erweitern, indem wir margins=True übergeben. Dies hat den Effekt, dass alle Zeilen- und Spaltenbeschriftungen hinzugefügt werden, wobei die entsprechenden Werte die Gruppenstatistiken für alle Daten innerhalb einer einzelnen Ebene sind:

[5]:
df.pivot_table(columns=["Title", "Language"], margins=True)
[5]:
Title Jupyter Tutorial PyViz Tutorial Python Basics
Language de en All de All de en All
2021-12 30134.0 6073.0 18103.5 4873.0 4873.0 427.0 95.0 261.0
2022-01 33295.0 7716.0 20505.5 3930.0 3930.0 276.0 226.0 251.0
2022-02 19651.0 6547.0 13099.0 2573.0 2573.0 525.0 157.0 341.0

In diesem Fall sind die Werte für All die Mittelwerte.

Um eine andere Aggregationsfunktion als mean zu verwenden, übergebt diese an das Schlüsselwortargument aggfunc. Mit sum erhaltet ihr beispielsweise die Summe:

[6]:
df.pivot_table(columns=["Title", "Language"], aggfunc=sum, margins=True)
[6]:
Title Jupyter Tutorial PyViz Tutorial Python Basics
Language de en All de All de en All
2021-12 30134.0 6073.0 36207.0 4873.0 4873.0 427.0 95.0 522.0
2022-01 33295.0 7716.0 41011.0 3930.0 3930.0 276.0 226.0 502.0
2022-02 19651.0 6547.0 26198.0 2573.0 2573.0 525.0 157.0 682.0

Wenn einige Kombinationen leer (oder anderweitig NA) sind, könnt ihr fill_value übergeben:

[7]:
df.pivot_table(columns=["Title", "Language"], aggfunc=sum, margins=True, fill_value=0)
[7]:
Title Jupyter Tutorial PyViz Tutorial Python Basics
Language de en All de All de en All
2021-12 30134 6073 36207 4873 4873 427 95 522
2022-01 33295 7716 41011 3930 3930 276 226 502
2022-02 19651 6547 26198 2573 2573 525 157 682

pivot_table-Optionen:

Funktionsname

Beschreibung

values

Spaltenname(n) zum Aggregieren; standardmäßig werden alle numerischen Spalten aggregiert

index

Spaltennamen oder andere Gruppenschlüssel, die in den Zeilen der resultierenden Pivot-Tabelle gruppiert werden sollen

columns

Spaltennamen oder andere Gruppenschlüssel, die in den Spalten der resultierenden Pivot-Tabelle gruppiert werden sollen

aggfunc

Aggregationsfunktion oder Liste von Funktionen (standardmäßig mean); kann eine beliebige Funktion sein, die in einem groupby-Kontext gültig ist

fill_value

ersetzt fehlende Werte in der Ergebnistabelle

dropna

wenn True, werden Spalten, deren Einträge alle NA sind, nicht berücksichtigt

margins

fügt Zeilen-/Spalten-Zwischensummen und Gesamtsummen ein (Standardeinstellung: False)

margins_name

Name, der für die Zeilen-/Spaltenbeschriftung verwendet wird, wenn margins=True übergeben wird, Standardwert ist All.

observed

Bei kategorialen Gruppenschlüsseln werden bei True nur die beobachteten Kategoriewerte in den Schlüsseln angezeigt und nicht alle Kategorien

Kreuztabellen#

Eine Kreuztabelle ist ein Spezialfall einer Pivot-Tabelle, die die Häufigkeit von Gruppen berechnet. Wollen wir z.B. im Rahmen einer Analyse diese Daten vielleicht ermitteln, welcher Titel in welcher Sprache erschienen ist, so könnten wir dafür pivot_table verwenden, aber die Funktion pandas.crosstab ist bequemer.

Hierfür setzen wir zunächst die bestehenden Index zurück:

[8]:
df.reset_index(inplace=True)
[9]:
pd.crosstab(df.Title, df.Language)
[9]:
Language de en
Title
Jupyter Tutorial 1 1
PyViz Tutorial 1 0
Python Basics 1 1

Die ersten beiden Argumente für crosstab können jeweils entweder ein Array oder eine Series oder eine Liste von Arrays sein.

Mit margins=True können wir uns auch die Summen der Spalten und Zeilen sowie die Gesamtsumme berechnen lassen:

[10]:
pd.crosstab(df.Title, df.Language, margins=True)
[10]:
Language de en All
Title
Jupyter Tutorial 1 1 2
PyViz Tutorial 1 0 1
Python Basics 1 1 2
All 3 2 5