14 KiB
Notizen SL Lektion 2
Thema: Datenverständnis, Explorative Datenanalyse, Feature Engineering Datum: 21.05.2026 Dozentin: Violeta Vogel
Überwachtes Lernen vs. Unüberwachtes Lernen
- beim Überwachten Lernen kennt das Modell die richtigen Antworten (Labels) und das Modell lernt diese vorherzusagen
- beim unüberwachten Lernen gibt es keine Labels, das Modell sucht selber Strukturen und Muster in den Daten
Datenverständnis
- Sammeln der Daten
- Beschaffen der in den Projektressourcen aufgeführten Daten
- Ersten Datenerfassungsbericht erstellen (Datenkatalog bilden)
- Daten beschreiben
- Erkennen wie jedes einzelne Feature aussieht
- In welchem Format sind die Daten?
- Wie viele Daten habe ich, wie gross ist der Datensatz?
- Daten erkunden
- Wie sind die Daten verteilt?
- Gibt es Beziehungen zwischen den Daten?
- Müssen eventuell Bereinigungen oder Aggregationen gemacht werden?
- Datenexplorationsbericht erstellen
- Datenqualität prüfen
- Sind die Daten vollständig?
- Datenqualitätsbericht erstellen
EDA: Ziele und Methoden
- Mustererkennung
- Datenbereinigung
- Visualisierung
- Hypothesengenerierung
EDA: Explorative Datenanalyse
- Anomalien
- Ausreisser, Datenpunkte die stark von der Norm abweichen
- Mögliche Anomalien
- Ausreisser → einzelne Datenpunkte die signifikant von Rest abweichen
- Kontextbezogene Anomalien → Daten die nur in einem bestimmten Kontext ungewöhnlich sind
- Kollektive Anomalien → eine Gruppe von Datenpunkten die gemeinsam abweichen, auch wenn sie einzeln normal wirken
- mögliche Anomalien nach Variablenart
- nicht numerische Daten
- fehlende Werte
- Duplikate
- Kategorien Variablen
- hohe Kardinalität (viele eindeutige Werte)
- nicht balancierte Daten
- numerische Variablen
- schiefe Verteilung
- Ausreisser
- Korrelationen
- diskrete Werte mit geringer Kardinalität (wenig eindeutige Werte)
- nicht numerische Daten
Klassierung
Die Klassierung in der deskriptiven Statistik ordnet viele, unterschiedliche Rohdaten in wenige, überschaubare Klassen (Intervalle) ein.
- Zweck: Reduzierung der Datenkomplexität (Muster und Trends erkennen)
- Vorgehen: Festlegung von Klassengrenzen
- Darstellung: Histogramme
- Nachteile: Durch Gruppierungen geht die exakte Messgenauigkeit verloren, da Einzelwerte nicht mehr erkennbar sind
Aufbau eines Data Frames
- Objekte / Beobachtungen sind in den Zeilen (rows)
- Merkmale / Attribute sind in den Spalten (columns) angegeben
- Spalten enthalten sprechende Namen, über welche sie angesprochen werden können
- pro Spalte ist ein Datentyp festgelegt, unterschiedliche Spalten können aber unterschiedliche Typen aufweisen
Skalenniveaus (Workshop 1)
Nominal
Das ist eine reine Kategorisierung. Werte sind nur Labels ohne jede Ordnung. Du kannst sagen "Rot ≠ Blau", aber nicht "Rot > Blau".
- Was geht:
- Gleichheit prüfen (= oder ≠)
- Was nicht geht:
- Reihenfolge
- Abstände
- Rechnen
- Beispiele:
- Geschlecht
- Postleitzahl
- Häusertyp (h/u/t im Melbourne-Dataset)
- Programmiersprache
- MAC-Adresse
- Sinnvolle Statistik:
- Modus
- Häufigkeiten
- Chi-Quadrat
- Mittelwert ist Unsinn ("durchschnittliche Postleitzahl"...)
- Stolperfalle:
- Wenn Kategorien als Zahlen codiert sind (z.B. Postcode = 3000), sieht's numerisch aus, ist aber nominal. Pandas wird's als int einlesen – die Klassifikation musst du selbst machen.
Ordinal
Ordnung ohne definierte Abstände. Du kannst Werte in eine sinnvolle Reihenfolge bringen, aber die Abstände dazwischen sind nicht definiert oder nicht gleich.
- Was geht:
- Gleichheit + Reihenfolge (<, >)
- Was nicht geht:
- Abstände interpretieren
- Rechnen
- Beispiele:
- Schulnoten (ist der Abstand zwischen 4 und 5 derselbe wie zwischen 5 und 6? Nicht wirklich)
- Likert-Skalen ("stimme zu" bis "stimme nicht zu")
- Militärränge
- T-Shirt-Grössen (S/M/L/XL)
- Bildungsabschluss
- Sinnvolle Statistik:
- Median
- Quantile
- Rangkorrelationen (Spearman)
- Stolperfalle:
- Likert-Skalen werden in der Praxis ständig wie metrische Daten behandelt (Mittelwert von "3.7 auf 5er-Skala") – formal falsch, aber pragmatisch verbreitet. Eine Dauerdebatte in der Sozialforschung.
Metrisch
Echte Zahlen mit definierten Abständen
- Was geht:
- Alles bisherige
- Abstände und Verhältnisse berechnen
- Hier wird's manchmal weiter unterteilt:
- Intervall: gleiche Abstände, aber kein echter Nullpunkt. Verhältnisse sind sinnlos. Beispiel: Temperatur in °C – 20°C ist nicht "doppelt so warm" wie 10°C, weil der Nullpunkt willkürlich gesetzt ist. Andere Beispiele: Kalenderjahre, IQ.
- Ratio (Verhältnis): gleiche Abstände plus echter Nullpunkt. Verhältnisse sind sinnvoll. Beispiel: Preis (0 € heisst tatsächlich "nichts"), Länge, Gewicht, Anzahl Zimmer.
- Sinnvolle Statistik:
- Mittelwert
- Standardabweichung
- Pearson-Korrelation
- alle parametrischen Tests
Ergebnisse Workshop 1 – Melbourne Housing Dataset
| Nr. | Column | Dtype | nominal | ordinal | metrisch |
|---|---|---|---|---|---|
| 0 | Unnamed: 0 | int64 | x | ||
| 1 | Suburb | object | x | ||
| 2 | Address | object | x | ||
| 3 | Rooms | int64 | x | ||
| 4 | Type | object | x | ||
| 5 | Price | float64 | x | ||
| 6 | Method | object | x | ||
| 7 | SellerG | object | x | ||
| 8 | Date | object | x | x | |
| 9 | Distance | float64 | x | ||
| 10 | Postcode | float64 | x | ||
| 11 | Bedroom2 | float64 | x | ||
| 12 | Bathroom | float64 | x | ||
| 13 | Car | float64 | x | ||
| 14 | Landsize | float64 | x | ||
| 15 | BuildingArea | float64 | x | ||
| 16 | YearBuilt | float64 | x | x | |
| 17 | CouncilArea | object | x | ||
| 18 | Lattitude | float64 | x | ||
| 19 | Longtitude | float64 | x | ||
| 20 | Regionname | object | x | ||
| 21 | Propertycount | float64 | x |
Anmerkung zu
DateundYearBuilt: Beide sind als ordinal und metrisch markiert. Das ist je nach Lesart vertretbar — ein Datum/Jahr hat eine klare Reihenfolge (ordinal) und gleiche Abstände ohne echten Nullpunkt (Intervall-metrisch).Unnamed: 0ist formal ein Index/Label und für ML eigentlich wertlos, auch wenn es als int64 "metrisch" aussieht (vgl. Nominal-Stolperfalle).
EDA in der Praxis (pandas)
Umgebung vorbereiten
import pandas as pd
import numpy as np
data = pd.read_csv('bank_data.csv', sep=';')
# Indizes der kategorialen bzw. numerischen Variablen für späteren Gebrauch
cat_vars = data.select_dtypes(include=['object']).columns
num_vars = data.select_dtypes(exclude=['object']).columns
- Merksatz Dtypes:
float64,int64→ numerisch;object→ nicht numerisch (kategorial)
Übersicht über den Data Frame
| Befehl | Zweck |
|---|---|
type(data) |
Objekttyp (pandas.core.frame.DataFrame) |
data.shape |
Dimensionen (rows, columns) |
data.info() |
Typ, Index, Dtypes, Non-Null-Count, Speicherbedarf |
data.iloc[0:6, 0:6] |
erste paar rows/columns (Position-basiert) |
data.head() / data.tail() |
erste / letzte rows |
Missing Values (NAs)
data.isna().sum().sum() # Anzahl NAs insgesamt
data.shape[0] - data.dropna().shape[0] # Anzahl rows mit mind. 1 NA
s = data.isna().sum(); print(s[s > 0]) # NAs pro column
- Wichtig: Anzahl NAs insgesamt ≠ Anzahl betroffener rows (eine row kann mehrere NAs haben)
Duplikate
- Duplikate = Beobachtungen, die in allen Variablen denselben Wert aufweisen
data.duplicated().sum()→ Anzahl.duplicated()gibt eine boolesche Serie zurück → zum Anzeigen oder Entfernen nutzbar- ob Duplikate als Fehler gelten, ist eine fachliche Entscheidung
Kategoriale Variablen – Kennzahlen
data.education.describe()liefert bei kategorialen Variablen:count: Anzahl nicht-Missing Valuesunique: Anzahl unterschiedliche Werte (Kategorien / Levels)top: häufigster Wert (→ Modalwert)freq: Häufigkeit des Modalwertes
data[cat_vars].describe()→ für alle kategorialen Variablen auf einmaldata.education.value_counts()→ Frequenztabelle, sortiert nach abnehmender Häufigkeit (Modalwert zuerst); NAs werden per Default nicht ausgewiesendata[cat_vars].nunique()→ Anzahl Kategorien je Variable- sehr hohe Werte (nahe
count) deuten auf ID-/Label-Charakter → kein Mehrwert für ML, und bei nominaler Umcodierung drohen sehr viele Dummy-Variablen
- sehr hohe Werte (nahe
Zero / Low Variance
- Zero Variance: alle Beobachtungen haben denselben Wert → kein Informationsgehalt, für ML wertlos
- Low Variance: ein Wert dominiert die anderen stark → meist wenig nützlich, fachlich abzuklären
- Konzept stammt aus der Analyse numerischer Variablen, lässt sich aber auch auf kategoriale anwenden
Visualisierung kategorialer Variablen
- Standard: Barchart —
data.education.value_counts().plot.bar()(Kategorien nach abnehmender Frequenz) - horizontaler Barplot: gut bei vielen Kategorien
- Pie Plot: in der Data Analytics eher unbeliebt (Flächen/Winkel schwer vergleichbar)
Numerische Variablen – Kennzahlen
data.age.describe()liefert:
| Kennzahl | Bedeutung |
|---|---|
count |
Anzahl (nicht-NA) Werte |
mean |
Mittelwert (arithmetisches Mittel) |
std |
Standardabweichung |
min |
Minimum (→ 0. Quartil) |
25% |
trennt kleinste 25 % ab → 1. Quartil |
50% |
Median → 2. Quartil |
75% |
trennt grösste 25 % ab → 3. Quartil |
max |
Maximum (→ 4. Quartil) |
meanundstdheissen parametrische Kennzahlen (parametrisieren Normalverteilungsmodelle, werden auch zum Skalieren verwendet)- die übrigen (Quartile/Median) sind nichtparametrische Kennzahlen (vgl. Boxplot)
describe()gibt bei numerischen Variablen keine unique-Zahl aus → bei Bedarfdata[num_vars].nunique()(sinnvoll v.a. bei Integer-Werten, um getarnte Kategorien zu finden)
Stolperfalle Variablennamen
- Zugriff
data.<variable>.<funktion>()klappt nur, wenn der Name den Python-Namenskonventionen entspricht - bei Namen wie
nr.employed(Punkt!) → traditioneller Zugriff über Spaltenindex nötig:
print(data.age.mean()) # ok
# print(data.nr.employed.mean()) # error
print(data['nr.employed'].mean()) # ok
Visualisierung numerischer Variablen
- Histogramm:
data.age.plot.hist()— Default 10 bins, viabins=20überschreibbar; zeigt Verteilungsform - Densityplot (KDE):
data.age.plot.kde()— Kernel Density Estimator: pro Beobachtung eine Normalverteilung der Fläche 1/n, additiv überlagert; mehr Detail als Histogramm, aber ressourcenhungrig - Boxplot:
data.age.plot.box(vert=False)— zeigt nichtparametrische Kennzahlen + ausreisserverdächtige Werte
Boxplot / Box-Whisker-Plot
- Box begrenzt durch 1. und 3. Quartil; Median innerhalb der Box markiert
- Whiskers ("Schnauzhaare") = Werte ausserhalb der Box bis zur Ausreissergrenze
- IQR (Interquartile Range) = 3. Quartil − 1. Quartil
- als Ausreisser markiert werden Werte:
- unterhalb von
Q1 − 1.5 × IQR - oberhalb von
Q3 + 1.5 × IQR
- unterhalb von
- gruppierte Boxplots zum Vergleich:
data.boxplot(column=['age'], by='education', vert=False)
Ausreisser prüfen
- sortierte Ausgabe hilft einzuschätzen, ob Randwerte echte Extremwerte sind:
print(data.age.sort_values().head(10)) # kleinste
print(data.age.sort_values(na_position="first").tail(10)) # grösste
- Beispiel
age: kleinster Wert (17) kommt mehrfach vor → plausibel; grösster Wert (116) setzt sich deutlich ab und ist fachlich unglaubwürdig → Ausreisser-Verdacht
Schiefe Verteilungen
- Benennung (rechts-/linksschief) richtet sich nach der Position der Extremwerte (der "Schwanz")
- rechtsschiefe Verteilungen sind in der Praxis häufig (z.B. Einkommen, hier
ageleicht,durationstark) - können oft mittels Logarithmieren in weniger schiefe Verteilungen transformiert werden
Interaktionen zwischen Variablen
Kategorial × kategorial
- Kreuztabelle (Mehrweg-Frequenztabelle):
pd.crosstab(data['job'], data['education']) - farblich formatieren:
ct.style.background_gradient(axis=None) - Heatmap (seaborn):
sns.heatmap(ct, annot=True, fmt='d')— erleichtert Interpretation - mit Chi-Quadrat liessen sich Zusammenhänge quantifizieren, Vergleiche sind aber schwierig
Toolwechsel: ab hier werden Visualisierungen mit seaborn (
sns) gemacht — High-Level-Interface auf matplotlib, einfacher zu bedienen. matplotlib = mächtiges Low-Level-Interface mit steiler Lernkurve.import matplotlib.pyplot as plt import seaborn as sns sns.set()
Numerisch × numerisch – Korrelationskoeffizient
- misst Stärke und Richtung des (linearen) Zusammenhangs zweier Variablen
rliegt zwischen −1 und +1:- +1 → perfekter positiver Zusammenhang (beide steigen; z.B. Körpergrösse/Gewicht)
- 0 → kein linearer Zusammenhang (z.B. Schuhgrösse/Intelligenz)
- −1 → perfekter negativer Zusammenhang (eine steigt, andere sinkt; z.B. Geschwindigkeit/Reisezeit)
- Anwendung: Feature Selection (Zusammenhang mit Target), EDA (Muster/Beziehungen), Modellinterpretation
- Achtung: misst nur lineare Zusammenhänge — Korrelation ≠ Kausalität
corr = data[['age', 'duration']].corr()
- Diagonale immer 1.0 (Identität); Matrix ist symmetrisch, da
cor(x,y) = cor(y,x)(kommutativ) - Korrelogramm (Heatmap) für die ganze Matrix:
plt.figure(figsize=(7, 6))
ax = sns.heatmap(corr, annot=True, fmt='.2f',
xticklabels=corr.columns, yticklabels=corr.columns,
cmap=sns.diverging_palette(10, 220, as_cmap=True),
vmin=-1, vmax=1)
- Scatterplot für zwei Variablen, optional Gruppen einfärben:
sns.scatterplot(x='age', y='duration', data=data, hue='y')
Maskieren starker Zusammenhänge
.corr()gibt selbst einen DataFrame → mit.where()lassen sich Werte maskieren, z.B. um in einem Korrelogramm nur stark korrelierte Paare zu zeigen:
mask = corr.where(abs(corr) >= 0.95)
# danach mask in sns.heatmap(...) statt corr verwenden
- nützlich, um redundante (hoch korrelierte) Features zu identifizieren → Kandidaten zum Entfernen