Skip to content

PySpark mit Null und NA umgehen: Praktische Cleaning-Rezepte

Updated on

Null-Werte zerstören Metriken, Joins und Exporte, wenn sie unkontrolliert bleiben. Unbedachte dropna‑Aufrufe können außerdem wertvolle Zeilen entfernen. Teams brauchen klare Muster, um Nulls in PySpark gezielt zu inspizieren, zu füllen, zu droppen oder sicher zu vergleichen.

Die eingebauten Null-Handler von PySpark – fillna, dropna, na.replace, coalesce und null-sichere Vergleiche – machen Pipelines vorhersagbar und transparent.

Möchtest du schnell Data Visualization aus einem Python Pandas DataFrame ohne Code erstellen?

PyGWalker ist eine Python-Bibliothek für Exploratory Data Analysis mit Visualization. PyGWalker (opens in a new tab) kann deinen Jupyter-Notebook-Workflow für Data Analysis und Data Visualization vereinfachen, indem es deinen pandas DataFrame (und polars DataFrame) in eine tableau‑ähnliche Benutzeroberfläche für visuelle Exploration verwandelt.

PyGWalker for Data visualization (opens in a new tab)

Schnelle Entscheidungshilfe

ZielAPIHinweise
Defaults auffüllenfillnaDict pro Spalte; Typen passend halten
Spärliche Zeilen droppendropnahow, thresh, subset steuern
Sentinel-Werte ersetzenna.replacePlatzhalter-Strings oder -Zahlen austauschen
Ersten Nicht-Null-Wert wählencoalesceSpalten nach Priorität kombinieren
Null-sichere Gleichheit<=> oder eqNullSafeBehandelt Nulls als gleich

Setup

from pyspark.sql import SparkSession, functions as F
 
spark = SparkSession.builder.appName("null-handling").getOrCreate()
 
df = spark.createDataFrame(
    [
        (1, "Alice", None, None),
        (2, "Bob", "basic", 0),
        (3, None, "premium", None),
    ],
    "id INT, name STRING, tier STRING, score INT",
)

Null-Muster inspizieren

null_stats = df.select(
    *[
        F.sum(F.col(c).isNull().cast("int")).alias(f"{c}_nulls")
        for c in df.columns
    ]
)
  • Zähle Nulls pro Spalte, bevor du entscheidest, ob du füllst oder droppst.

Fehlende Werte auffüllen

filled = df.fillna({"name": "unknown", "tier": "basic", "score": 0})
  • Gib ein Dict an, um die Typen konsistent zu halten; vermeide es, numerische Spalten mit Strings zu füllen.
  • Für Date/Timestamp-Spalten Domain-Defaults verwenden (to_date('1970-01-01')).

Zeilen selektiv droppen

drop_sparse = df.dropna(thresh=3)          # keep rows with >=3 non-null values
drop_missing_tier = df.dropna(subset=["tier"])
  • thresh schützt vor übermäßigem Droppen.
  • Bevorzuge Spalten-Subsets gegenüber pauschalem dropna(), um nützliche Zeilen zu erhalten.

Sentinel-Werte ersetzen

clean_sent = df.na.replace({"N/A": None, "": None}, subset=["tier", "name"])
  • Konvertiere Platzhalter-Strings in echte Nulls, bevor du füllst oder droppst.

Mit Coalesce den ersten Nicht-Null wählen

with_fallback = df.withColumn("primary_tier", F.coalesce("tier", F.lit("basic")))
  • coalesce gibt das erste Nicht-Null-Argument zurück.

Null-sichere Vergleiche

matches = df.where(F.expr("tier <=> 'premium'"))
  • <=> (oder eqNullSafe) behandelt zwei Nulls als gleich; ein normales = liefert für Null-Vergleiche selbst Null.

Downstream-Joins absichern

  • Fülle Join-Keys nur, wenn es fachlich erlaubt ist; ansonsten Null-Keys explizit filtern.
  • Für Fact‑zu‑Dimension‑Joins entscheiden: Null-Keys vor dem Join droppen oder beibehalten und später behandeln.

Minimale Cleaning-Pipeline

clean = (
    df
    .na.replace({"N/A": None, "": None})
    .dropna(subset=["name"])  # require a name
    .fillna({"tier": "basic", "score": 0})
    .withColumn("tier_clean", F.coalesce("tier", F.lit("basic")))
)

Diese Sequenz standardisiert Platzhalter, behält Pflichtfelder bei, füllt mit fachlichen Defaults auf und hinterlässt eine klare Fallback-Spalte für Reporting.