Files
cas-pml/SL/notizen/L2_Notizen.md
T

14 KiB
Raw Blame History

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

  1. Sammeln der Daten
    • Beschaffen der in den Projektressourcen aufgeführten Daten
    • Ersten Datenerfassungsbericht erstellen (Datenkatalog bilden)
  2. Daten beschreiben
    • Erkennen wie jedes einzelne Feature aussieht
    • In welchem Format sind die Daten?
    • Wie viele Daten habe ich, wie gross ist der Datensatz?
  3. Daten erkunden
    • Wie sind die Daten verteilt?
    • Gibt es Beziehungen zwischen den Daten?
    • Müssen eventuell Bereinigungen oder Aggregationen gemacht werden?
    • Datenexplorationsbericht erstellen
  4. 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)

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 Date und YearBuilt: 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: 0 ist 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 Values
    • unique: 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 einmal
  • data.education.value_counts() → Frequenztabelle, sortiert nach abnehmender Häufigkeit (Modalwert zuerst); NAs werden per Default nicht ausgewiesen
  • data[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

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)
  • mean und std heissen 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 Bedarf data[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, via bins=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
  • 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 age leicht, duration stark)
  • 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
  • r liegt 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