Skip to content

Pandas Data Cleaning: Praxis-Workflow

Updated on

Schmutzige Daten blockieren Analysen früh. Ad-hoc-fillna oder String-Ersetzungen verbergen oft echte Probleme: falsche Datentypen, stille Duplikate oder Ausreißer, die Statistiken verzerren.

PAS-Rahmen:

  • Problem: Gemischte Typen, fehlende Werte und doppelte Datensätze zerstören Joins und verzerren Kennzahlen.
  • Agitation: Schnelle Einzel-Fixes verschleiern Probleme bis spät im Projekt und verursachen Nacharbeit.
  • Lösung: Ein wiederholbarer Bereinigungs-Check: Dtypes standardisieren, Nulls bewusst behandeln, Ausreißer abfedern, Duplikate entfernen, zum Schluss validieren.

Workflow auf einen Blick

SchrittWas tunBeispiel
1. ProfilierenSpalten, Nulls, Uniques prüfendf.info(), df.describe(include="all")
2. Spalten normalisierenNamen/Strings trimmen & vereinheitlichendf.columns = df.columns.str.strip().str.lower()
3. Dtypes fixento_datetime, to_numeric, astype("category")df["date"] = pd.to_datetime(df["date"], errors="coerce")
4. Fehlende WerteLöschen oder gezielt füllendf["age"] = df["age"].fillna(df["age"].median())
5. AusreißerKappen oder flaggendf["rev_cap"] = df["revenue"].clip(upper=df["revenue"].quantile(0.99))
6. DuplikateExakt/teilweise entfernendf.drop_duplicates(subset=["id", "date"], keep="last")
7. ValidierenRegeln erzwingenassert df["score"].between(0,100).all()

1) Schnell profilieren

summary = {
    "rows": len(df),
    "columns": df.shape[1],
    "nulls": df.isna().sum(),
    "unique_counts": df.nunique(),
}
  • Mixed Types früh erkennen (df.info()).
  • Schiefe Verteilungen mit df.describe(percentiles=[0.01,0.99]) prüfen.

2) Spalten und Text normalisieren

df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
df["country"] = df["country"].str.strip().str.title()
  • Standardisierte Namen vereinfachen Joins und Code.
  • Bei ungewöhnlichen Zeichen: .str.normalize("NFKC").

3) Datentypen korrigieren

df["date"] = pd.to_datetime(df["date"], errors="coerce", utc=True)
df["amount"] = pd.to_numeric(df["amount"], errors="coerce")
df["segment"] = df["segment"].astype("category")
  • errors="coerce" macht Fehler sichtbar als NaT/NaN.
  • convert_dtypes() liefert nullable, speichereffiziente Typen in einem Rutsch.

4) Fehlende Werte behandeln

df["age"] = df["age"].fillna(df["age"].median())
df["city"] = df["city"].fillna("Unknown")
df = df.dropna(subset=["id"])  # Pflichtschlüssel
  • Pro Spalte entscheiden: numerisch → Median/Mean; kategorisch → Modus/Platzhalter.
  • Signal erhalten per Flag: df["age_imputed"] = df["age"].isna().

5) Ausreißer behandeln

upper = df["revenue"].quantile(0.99)
lower = df["revenue"].quantile(0.01)
df["revenue_capped"] = df["revenue"].clip(lower=lower, upper=upper)
  • Für Verhältnisse ggf. Z-Scores: abs(z) < 3.
  • Finanzdaten lieber kappen statt löschen, um Counts zu bewahren.

6) Duplikate sicher entfernen

df = df.drop_duplicates(subset=["id", "date"], keep="last")
  • Uniqueness-Key prüfen: assert df.duplicated(["id"]).sum() == 0.
  • Für unscharfe Matches vorher normalisieren (z. B. E-Mails kleinschreiben).

7) Vor Export validieren

assert df["score"].between(0, 100).all()
valid_segments = {"basic", "pro", "enterprise"}
assert df["segment"].isin(valid_segments).all()
  • pd.testing.assert_frame_equal in Tests nutzen, um Outputs zu vergleichen.
  • Leichte Row- und Null-Checks in Pipelines einbauen, um Regressionen zu fangen.

End-to-End-Minipipeline

def clean(df):
    df = df.copy()
    df.columns = df.columns.str.strip().str.lower()
    df["date"] = pd.to_datetime(df["date"], errors="coerce")
    df["amount"] = pd.to_numeric(df["amount"], errors="coerce")
    df["amount"] = df["amount"].fillna(df["amount"].median())
    df["segment"] = df["segment"].fillna("unknown").str.lower()
    df = df.dropna(subset=["id"])
    df = df.drop_duplicates(subset=["id", "date"], keep="last")
    assert df["amount"].ge(0).all()
    return df
  • Zuerst kopieren, um Eingaben nicht zu mutieren.
  • Mit df.pipe(clean) bleibt der Code lesbar.

Verwandte Guides


Wichtigste Punkte

  • Namen standardisieren, Dtypes erzwingen, Nulls bewusst behandeln.
  • Ausreißer kappen oder flaggen statt still löschen.
  • Keys und Wertebereiche validieren, bevor Daten an BI/Analytics gehen.