Skip to content

PySpark: Lidando com Null e NA – Receitas Práticas de Limpeza

Updated on

Nulls quebram métricas, joins e exports quando passam despercebidos. Chamadas silenciosas a dropna também podem apagar linhas valiosas. As equipes precisam de padrões deliberados para inspecionar, preencher, descartar ou comparar nulls com segurança em PySpark.

Os manipuladores de null embutidos no PySpark — fillna, dropna, na.replace, coalesce e comparações null-safe — mantêm os pipelines previsíveis e transparentes.

Quer criar rapidamente Data Visualization a partir de um DataFrame Pandas em Python sem escrever código?

PyGWalker é uma biblioteca Python para Exploratory Data Analysis com Visualization. PyGWalker (opens in a new tab) pode simplificar o fluxo de trabalho de análise e visualização de dados no seu Jupyter Notebook, transformando seu pandas dataframe (e polars dataframe) em uma interface alternativa ao Tableau para exploração visual.

PyGWalker for Data visualization (opens in a new tab)

Guia rápido de decisão

ObjetivoAPIObservações
Preencher valores padrãofillnaDicionário por coluna; combine tipos
Descartar linhas esparsasdropnaControle how, thresh, subset
Substituir sentinelasna.replaceTroque strings ou números de placeholder
Escolher primeiro não-nullcoalesceCombine colunas por prioridade
Igualdade null-safe<=> ou eqNullSafeTrata nulls como iguais

Configuração

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

Inspecionar padrões de null

null_stats = df.select(
    *[
        F.sum(F.col(c).isNull().cast("int")).alias(f"{c}_nulls")
        for c in df.columns
    ]
)
  • Conte nulls por coluna antes de decidir preencher ou descartar.

Preencher valores ausentes

filled = df.fillna({"name": "unknown", "tier": "basic", "score": 0})
  • Forneça um dicionário para manter os tipos alinhados; evite preencher numéricos com strings.
  • Para datas/timestamps, use padrões de domínio (to_date('1970-01-01')).

Descartar linhas seletivamente

drop_sparse = df.dropna(thresh=3)          # mantém linhas com >=3 valores não-nulos
drop_missing_tier = df.dropna(subset=["tier"])
  • thresh protege contra descartes excessivos.
  • Prefira subconjuntos de colunas em vez de um dropna() geral para preservar linhas úteis.

Substituir valores sentinela

clean_sent = df.na.replace({"N/A": None, "": None}, subset=["tier", "name"])
  • Converta strings de placeholder em nulls reais antes de preencher ou descartar.

Usar coalesce para pegar o primeiro não-null

with_fallback = df.withColumn("primary_tier", F.coalesce("tier", F.lit("basic")))
  • coalesce retorna o primeiro argumento não-nulo na lista.

Comparações null-safe

matches = df.where(F.expr("tier <=> 'premium'"))
  • <=> (ou eqNullSafe) trata dois nulls como iguais; o = normal retorna null para comparações com null.

Protegendo joins downstream

  • Preencha chaves de join apenas quando as regras de negócio permitirem; caso contrário filtre chaves nulas explicitamente.
  • Para joins fato–dimensão, decida: descartar chaves nulas antes do join ou preservá-las e tratar depois.

Pipeline mínimo de limpeza

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

Essa sequência padroniza placeholders, mantém campos obrigatórios, preenche com padrões de negócio e deixa uma coluna de fallback clara para relatórios.