Skip to content

PySpark Manejo de Null y NA: Recetas prácticas de limpieza

Updated on

Los nulls rompen métricas, joins y exports cuando se dejan sin controlar. Llamadas silenciosas a dropna también pueden borrar filas valiosas. Los equipos necesitan patrones deliberados para inspeccionar, rellenar, eliminar o comparar nulls de forma segura en PySpark.

Los manejadores de null incorporados de PySpark—fillna, dropna, na.replace, coalesce y las comparaciones null-safe—mantienen los pipelines predecibles y transparentes.

¿Quieres crear rápidamente Data Visualization desde un DataFrame de Python Pandas sin escribir código?

PyGWalker es una librería de Python para Exploratory Data Analysis con Visualization. PyGWalker (opens in a new tab) puede simplificar tu flujo de trabajo de análisis y visualización de datos en Jupyter Notebook, convirtiendo tu pandas dataframe (y polars dataframe) en una interfaz de usuario tipo tableau para exploración visual.

PyGWalker for Data visualization (opens in a new tab)

Guía rápida de decisión

ObjetivoAPINotas
Rellenar valores por defectofillnaDiccionario por columna; respetar tipos
Eliminar filas escasasdropnaControlar how, thresh, subset
Reemplazar sentinelasna.replaceCambiar strings o números marcadores
Tomar el primer no nulocoalesceCombinar columnas por prioridad
Igualdad null-safe<=> o eqNullSafeTrata los nulls como iguales

Configuración

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",
)

Inspeccionar patrones de null

null_stats = df.select(
    *[
        F.sum(F.col(c).isNull().cast("int")).alias(f"{c}_nulls")
        for c in df.columns
    ]
)
  • Cuenta los nulls por columna antes de decidir si rellenar o eliminar.

Rellenar valores faltantes

filled = df.fillna({"name": "unknown", "tier": "basic", "score": 0})
  • Proporciona un diccionario para mantener alineados los tipos; evita rellenar numéricos con strings.
  • Para fechas/timestamps, usa valores por defecto de dominio (to_date('1970-01-01')).

Eliminar filas selectivamente

drop_sparse = df.dropna(thresh=3)          # keep rows with >=3 non-null values
drop_missing_tier = df.dropna(subset=["tier"])
  • thresh protege frente a eliminar demasiado.
  • Prefiere subconjuntos de columnas antes que un dropna() global para preservar filas útiles.

Reemplazar valores sentinela

clean_sent = df.na.replace({"N/A": None, "": None}, subset=["tier", "name"])
  • Convierte strings marcadores en nulls reales antes de rellenar o eliminar.

Coalesce para tomar el primer no nulo

with_fallback = df.withColumn("primary_tier", F.coalesce("tier", F.lit("basic")))
  • coalesce devuelve el primer valor no nulo en la lista de argumentos.

Comparaciones null-safe

matches = df.where(F.expr("tier <=> 'premium'"))
  • <=> (o eqNullSafe) trata dos nulls como iguales; el operador = normal devuelve null al comparar con null.

Proteger joins posteriores

  • Rellena claves de join solo cuando las reglas de negocio lo permitan; de lo contrario filtra explícitamente las claves nulas.
  • Para joins fact-to-dimension, decide: eliminar claves nulas antes del join o preservarlas y gestionarlas más adelante.

Pipeline mínimo de limpieza

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")))
)

Esta secuencia estandariza marcadores, mantiene campos requeridos, rellena con valores por defecto de negocio y deja una columna de respaldo clara para reporting.