Kreuztabellen in Pandas

Kategoriale Daten werden in der Regel über Auszählungen analysiert. Wie sie einfache Häufigkeits- bis hin zu komplexen Kreuztabellen mit pandas erstellen, erfahren Sie in diesem Beitrag.

crosstab und pivot_table

Grundsätzlich liefert pandas 2 Instrumente, mit denen sich komplexere Häufigkeitsauszählungen umsetzen lassen. Dies sind die Funktionen crosstab und pivot_table. Beide Methoden unterscheiden sich dabei in einigen Nuancen:

  • crosstab:
    • crosstab ist eine Funktion.
    • Input sind einzelne Spalten aus Arrays oder DataFrames.
    • Die Default-Aggregatsfunktion ist ‚len‘.
  • pivot_table:
    • pivot_table ist eine Klassenmethode von DataFrame.
    • Input muss vom Typ DataFrame sein.
    • Die Default-Aggregatsfunktion ist ‚mean‘.
    • pivot_table arbeitet mit den gesamten Daten.

Da crosstab expliziter arbeitet als pivot_table, empfehle für die Anwendung von Häufigkeitsauszählungen diese Funktion.

Wie wir noch sehen werden, ist crosstab sehr flexibel: Neben Auszählungen einzelner Spalten können Kreuztabellen und verschachtelte Kreuztabellen erzeugt werden. Auch Aggregationen mit statistischen Funktionen lassen sich mit crosstab umsetzen.

Der Beispieldatensatz ‚titanic‘

Die Methode crosstab wird an dem Beispieldatensatz ‚titanic‘ vorgeführt. Wenn Sie den hier dargestellten Quellcode lokal ausführen möchten, können Sie sich dazu den Datensatz hier downloaden.

Die ersten 5 Zeilen des Datensatzes sind unten dargestellt. Außerdem finden Sie weiter unten eine Kurzbeschreibung der Daten.

In [2]:
import pandas as pd
titanic = pd.read_csv("../__data/Titanic.csv")

titanic.head()
Out[2]:
survived pclass name sex age sibsp parch ticket fare cabin embarked
0 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th… female 38.0 1 0 PC 17599 71.2833 C85 C
2 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S

 

Einfache Auszählung einzelner Spalten

Vielleicht ist Ihnen die Series-Methode value_counts bekannt. Diese zählt die Werte einer Series aus und returniert wiederum eine Series. Crosstab kann diesen Zweck in gleicher Weise erfüllen, mit dem einen Unterschied, nicht eine Series, sondern einen DataFrame zu returnieren.

In [24]:
titanic['sex'].value_counts() # Returniert eine Series  
Out[24]:
male      577
female    314
Name: sex, dtype: int64
In [76]:
# Returniert einen DataFrame
pd.crosstab(index=titanic['sex'], # Die Ausprägungen der Spalte sex werden Zeilenindex 
            columns="Count") # Wird ein einfacher String übergeben, ist dieser das Spaltenlabel
Out[76]:
sex female male
row_0
count 314 577
In [ ]:
# Wie oben, nur Zeilen und Spalten vertauscht:
pd.crosstab(index='Count', # Wird ein einfacher String übergeben, ist dieser das Zeilenlabel
            columns=titanic['sex']) # Die Ausprägungen der Spalte sex werden Spaltenlabel

Kreuztabellen

Um Kreuztabellen zu erstellen, werden die Argemente index (entspricht den Zeilen der Tabelle) und columns (die Spalten) mit Array-Objekten besetzt.

In [17]:
pd.crosstab(index=titanic['sex'], columns=titanic['pclass'])
Out[17]:
pclass 1 2 3
sex
female 94 76 144
male 122 108 347

Verschachtelte Kreuztabellen

Um Kreuztabellen zu schachteln, können den Argumenten index und columns Listen mit Array-Objekten übergeben werden.

In [18]:
pd.crosstab(index=[titanic['pclass'], titanic['sex']], columns='Count')
Out[18]:
col_0 Count
pclass sex
1 female 94
male 122
2 female 76
male 108
3 female 144
male 347

Aggregationen

Auch Datenaggregationen können mit crosstab vorgenommen werden. Dem Argument values wird dazu ein Array-Objekt mit Werten übergeben, welche mit den Funktionen aus dem Argument aggfunc ausgewertet werden. Wie in dem Beispiel zu sehen ist, können auch mehrere Aggregationsfunktionen als Liste übergeben werden. Wie in dem Beispiel leider auch zu sehen ist, können dem Argument columns nicht mehrere Spaltenlabel übergeben werden – hier hat die Funktion crosstab noch Verbesserungspotenzial.

In [88]:
import numpy as np
pd.crosstab(index=titanic['sex'], columns="Aggregat", values=titanic['age'], aggfunc=[len,np.mean])
Out[88]:
len mean
col_0 Aggregat Aggregat
sex
female 314.0 27.915709
male 577.0 30.726645

Randverteilungen und Prozentwerte

Fortgeschrittene Tabellen enthalten bspw. Randverteilungen und Prozentwerte. Die Randverteilung wird der Tabelle mit dem Argument margins=True hinzugefügt. Mit applymap wird jede Zelle der Tabelle in den entsprechenden Prozentwert transformiert. (Erfahren Sie hier mehr über applymap.)

In [95]:
pd.crosstab(index=titanic['sex'], columns=titanic['pclass'], margins=True).applymap(lambda r: r/len(titanic))
Out[95]:
pclass 1 2 3 All
sex
female 0.105499 0.085297 0.161616 0.352413
male 0.136925 0.121212 0.389450 0.647587
All 0.242424 0.206510 0.551066 1.000000

Sollen die Zeilen oder Spaltenprozente berechnet werden, kann dies nach dem Split-Apply-Combine Ansatz geschehen. Split-Apply-Combine wird in Python mit der Funktion apply umgesetzt.

In [6]:
# Spaltenprozente:
pd.crosstab(index=titanic['sex'], columns=titanic['pclass'], margins=False).apply(lambda zeile: zeile/zeile.sum(), axis=0)
Out[6]:
pclass 1 2 3
sex
female 0.435185 0.413043 0.293279
male 0.564815 0.586957 0.706721
In [7]:
# Zeilenprozente:
pd.crosstab(index=titanic['sex'], columns=titanic['pclass'], margins=False).apply(lambda zeile: zeile/zeile.sum(), axis=1)
Out[7]:
pclass 1 2 3
sex
female 0.299363 0.242038 0.458599
male 0.211438 0.187175 0.601386