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.
Guia rápido de decisão
| Objetivo | API | Observações |
|---|---|---|
| Preencher valores padrão | fillna | Dicionário por coluna; combine tipos |
| Descartar linhas esparsas | dropna | Controle how, thresh, subset |
| Substituir sentinelas | na.replace | Troque strings ou números de placeholder |
| Escolher primeiro não-null | coalesce | Combine colunas por prioridade |
| Igualdade null-safe | <=> ou eqNullSafe | Trata 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"])threshprotege 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")))coalesceretorna o primeiro argumento não-nulo na lista.
Comparações null-safe
matches = df.where(F.expr("tier <=> 'premium'"))<=>(oueqNullSafe) 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.
