PySpark Select, Filter e withColumn: Receitas Essenciais de DataFrame
Updated on
DataFrames desorganizados atrasam qualquer pipeline: colunas erradas, filtros inseguros e casts frágeis criam erros silenciosos. As equipes precisam de padrões repetíveis para selecionar, filtrar e derivar colunas, para manter os jobs Spark previsíveis.
As APIs select, filter/where e withColumn do PySpark resolvem isso ao manter as transformações explícitas, com tipos seguros e testáveis. Este guia mostra os principais padrões e como evitar armadilhas comuns.
Quer criar rapidamente Data Visualization a partir de um DataFrame do Python Pandas sem escrever código?
PyGWalker é uma biblioteca Python para Exploratory Data Analysis com Visualização. O PyGWalker (opens in a new tab) pode simplificar seu fluxo de análise e visualização de dados no Jupyter Notebook, transformando seu pandas dataframe (e polars dataframe) em uma interface de usuário alternativa ao Tableau para exploração visual.
Mapa para leitura
| Tarefa | API | Quando usar |
|---|---|---|
| Escolher/renomear colunas | select, alias | Manter apenas as colunas necessárias; evite selectExpr quando for simples |
| Filtragem de linhas | filter / where | Ambas idênticas; encadeie condições com & e | |
| Colunas derivadas/condicionais | withColumn, when/otherwise | Adicionar ou substituir colunas com lógica |
| Expressões estilo SQL | selectExpr, expr | Aritmética rápida ou funções SQL sem muitos imports |
| Casting seguro | cast, try_cast (Spark 3.5+) | Impor tipos sem lançar erro em valores ruins |
Configuração e dados de exemplo
from pyspark.sql import SparkSession
from pyspark.sql import functions as F
spark = SparkSession.builder.appName("select-filter-withcolumn").getOrCreate()
df = spark.createDataFrame(
[
(1, "Alice", "2025-11-01", "premium", "42"),
(2, "Bob", "2025-11-02", "basic", "x"),
(3, "Cara", "2025-11-02", None, "7"),
],
"id INT, name STRING, signup_date STRING, tier STRING, score STRING",
)Selecione apenas o que você precisa
slim = df.select(
"id",
F.col("name").alias("customer_name"),
F.to_date("signup_date").alias("signup_dt"),
)selectmantém as projeções explícitas e evita leituras amplas desnecessárias.- Use
aliaspara nomes mais amigáveis.
Filter / where: APIs idênticas
active = slim.where(
(F.col("signup_dt") >= "2025-11-01")
& (F.col("customer_name") != "Bob")
)filterewheresão iguais; escolha uma por legibilidade.- Combine condições com
&e|; coloque cada condição entre parênteses. - Verificações de nulo:
isNull()/isNotNull()evitam surpresas.
withColumn para valores derivados e condicionais
scored = active.withColumn(
"score_int",
F.when(F.col("score").rlike("^[0-9]+$"), F.col("score").cast("int"))
.otherwise(None),
)withColumnadiciona ou substitui colunas; mantenha nomes únicos para evitar sobrescritas acidentais.when/otherwisedefine uma lógica de ramificação clara.
selectExpr para expressões rápidas
expr_df = df.selectExpr(
"id",
"upper(name) AS name_upper",
"to_date(signup_date) AS signup_dt",
"CASE WHEN tier = 'premium' THEN 1 ELSE 0 END AS is_premium",
)- Útil para cálculos no estilo SQL sem muitos imports de
functions. - Mantenha lógicas complexas em
withColumnnormal para melhor legibilidade e testes.
Padrões de casting seguro
typed = (
df
.withColumn("score_int", F.col("score").cast("int"))
.withColumn("signup_ts", F.to_timestamp("signup_date"))
)- Prefira casts explícitos; evite depender de inferência de schema em fontes CSV.
- No Spark 3.5+,
try_castretorna null em vez de falhar em valores inválidos.
Verificações rápidas de qualidade de dados
from pyspark.sql import functions as F
bad_counts = df.select(
F.sum(F.col("score").rlike("^[0-9]+$").cast("int")).alias("valid_scores"),
F.sum(F.col("score").rlike("^[^0-9]").cast("int")).alias("invalid_scores"),
)- Valide antes de escrever; agregações pequenas revelam problemas cedo.
- Use
count+isNullpara medir taxas de ausência em colunas chave.
Armadilhas comuns e correções
- Condições sem parênteses: sempre envolva cada cláusula booleana ao usar
&/|. - Sobrescrita acidental de coluna: confira
df.columnsou use novos nomes comwithColumn. - Datas em string sem parsing: converta com
to_date/to_timestampantes de comparar. - Comparações sensíveis a null: use
isNull/isNotNullpara evitar surpresas de lógica de três valores.
Exemplo de pipeline mínimo
clean = (
df
.select("id", "name", "signup_date", "tier", "score")
.where(F.col("tier").isNotNull())
.withColumn("signup_dt", F.to_date("signup_date"))
.withColumn(
"score_int",
F.when(F.col("score").rlike("^[0-9]+$"), F.col("score").cast("int")),
)
)Isso mantém as seleções enxutas, filtros explícitos e colunas derivadas tipadas antes das etapas posteriores de escrita.
