Curso
Os DataFrame do PySpark são essenciais quando você cria pipelines escaláveis no Spark. Uma coisa importante pra lembrar é que os DataFrame são imutáveis. Isso quer dizer que, depois de criar um, você não pode alterá-lo diretamente; sempre que fizer uma alteração, você vai ter um novo DataFrame. É aí que entra o PySpark withColumn()
. Isso ajuda você a adicionar, atualizar ou alterar colunas, mas como os DataFrame não mudam no lugar, você sempre reatribui o resultado a uma nova variável.
Neste tutorial, vou te mostrar como usar o withColumn()
para moldar e ajustar seus conjuntos de dados, seja para criar recursos, limpar tipos ou adicionar lógica.
O que é withColumn() no PySpark?
Resumindo, withColumn()
retorna um novo DataFrame com uma coluna adicionada ou substituída. Como os DataFrame não mudam, você precisa atribuir esse valor de retorno, df = df.withColumn(...)
.
Nos bastidores, cada chamada para withColumn()
adiciona uma projeção no plano lógico. Tudo bem se você estiver fazendo só uma ou duas, mas encadear muitas pode deixar o plano pesado, fazendo o Spark rodar bem mais devagar.
É novo no PySpark? Você pode dominar os fundamentos para lidar com big data com facilidade, aprendendo a processar, consultar e otimizar conjuntos de dados enormes para análises poderosas em nosso curso Introdução ao PySpark.
Principais usos do PySpark com a função withColumn()
Vamos ver as principais maneiras de usar o withColumn()
:
Adicionando uma coluna constante
Digamos que você queira adicionar um carimbo de data/hora ou um sinalizador. Use lit()
ou typedLit()
de pyspark.sql.functions
. Por exemplo:
from pyspark.sql.functions import lit
df = df.withColumn("ingest_date", lit("2025-07-29"))
Criando uma coluna a partir de dados que já existem
Talvez você queira um valor derivado, juntar strings ou calcular um total. Você pode fazer:
from pyspark.sql.functions import col, expr
df = df.withColumn("full_name", col("first_name") + expr(" ' ' + last_name"))
Transformações aritméticas ou baseadas em expressões também se encaixam aqui.
Sobrescrevendo uma coluna que já existe
Se você já tem uma coluna e quer alterá-la, basta usar withColumn()
para substituí-la:
df = df.withColumn("age", col("age").cast("integer"))
Não precisa excluir e adicionar de novo.
Tipos de dados de conversão
Mudar o tipo de uma coluna é bem simples:
df = df.withColumn("price", col("price").cast("decimal(10,2)"))
Acho isso bem útil quando estou lendo JSON ou CSV soltos, onde os tipos aparecem como strings.
Se você está procurando mais exemplos do que é o PySpark e como você pode usá-lo com exemplos, recomendo nosso tutorial Introdução ao PySpark.
Lógica condicional e expressões when()
Às vezes, você precisa fazer mais do que só contas simples. Talvez você esteja criando uma coluna de status com base em uma pontuação. Ou sinalizar entradas com base em um conjunto de regras. É aí que entra o site when()
, de pyspark.sql.functions
. Pense nisso como uma declaração “ IF
”. Você pode combiná-lo com otherwise()
para cobrir vários caminhos.
É assim que fica:
from pyspark.sql.functions import when
df = df.withColumn(
"grade",
when(col("score") >= 90, "A")
.when(col("score") >= 80, "B")
.when(col("score") >= 70, "C")
.otherwise("F")
)
Parece quase inglês simples: Se a nota for pelo menos 90, então A. Caso contrário, se for 80, então B. Continue... e se nenhuma dessas opções corresponder, dê um F. É bem expressivo, e o Spark transforma essa lógica numa expressão eficiente nos bastidores. Sem loops aninhados, sem chamadas de “ apply()
”, só DAGs limpos e planos de execução claros.
Isso é útil quando você quer evitar mudar para SQL ou sobrecarregar seu código com UDFs.
Você pode aprender a mexer nos dados e criar conjuntos de recursos de machine learning no Spark usando SQL em Python com o nosso tutorial Introdução ao Spark SQL em Python .
Transformando colunas com funções integradas e definidas pelo usuário
Você vai precisar formatar ou reestruturar colunas, colocar as letras em maiúsculas, dividir em partes, juntar valores e assim por diante. O PySpark tem uma biblioteca cheia de funções integradas que funcionam direto dentro de um withColumn()
.
Aqui vai um exemplo:
from pyspark.sql.functions import upper, concat_ws, split
df = df.withColumn("full_caps", upper(col("name")))
df = df.withColumn("city_state", concat_ws(", ", col("city"), col("state")))
df = df.withColumn("first_word", split(col("description"), " ").getItem(0))
Agora, os embutidos são ótimos. Rápido, nativo e otimizado. Mas, às vezes, você tem uma regra única que não se encaixa em nenhuma categoria. É aí que entram as funções definidas pelo usuário (UDFs).
Usando uma UDF
Digamos que você queira calcular o comprimento de uma string e rotulá-la:
from pyspark.sql.functions import udf
from pyspark.sql.types import StringType
def label_length(x):
return "short" if len(x) < 5 else "long"
label_udf = udf(label_length, StringType())
df = df.withColumn("name_length_label", label_udf(col("name")))
Simples assim. Mas cuidado, os UDFs têm uma sobrecarga. Eles pegam os dados do mecanismo otimizado, executam em Python e, em seguida, os reempacotam. Isso é legal quando necessário, mas para tarefas de alto volume, prefira expressões SQL ou integradas, se possível.
Aprenda a criar, otimizar e usar UDFs do PySpark, incluindo UDFs do Pandas, para lidar com transformações de dados personalizadas de forma eficiente e melhorar o desempenho do Spark com nosso tutorial Como usar UDFs do PySpark e UDFs do Pandas de forma eficaz.
Considerações sobre desempenho e práticas avançadas
Em algum momento, todo mundo que usa o PySpark se depara com isso: você fica empilhando chamadas de ` withColumn()
` e seu pipeline fica super lento. O motivo? Cada chamada adiciona uma nova camada ao plano lógico, que o Spark precisa analisar, otimizar e executar.
Se você estiver adicionando apenas uma ou duas colunas, tudo bem. Mas se você estiver encadeando cinco, seis ou mais, é melhor começar a pensar de outra forma.
Usar select()
ao adicionar muitas colunas
Em vez de chamar withColumn()
várias vezes, crie uma nova lista de colunas usando select()
:
df = df.select(
"*",
(col("salary") * 0.1).alias("bonus"),
(col("age") + 5).alias("age_plus_five")
)
Essa abordagem cria o plano lógico de uma só vez.
Saiba mais sobre select()
e outros métodos em nossa folha de dicas do PySpark : Tutorial sobre Spark em Python.
E quanto a withColumns()
?
Introduzido no Spark 3.3, o withColumns()
permite adicionar várias colunas de uma só vez. Chega de ligações repetidas. É um método tipo dicionário:
df = df.withColumns({
"bonus": col("salary") * 0.1,
"age_plus_five": col("age") + 5
})
Nem todo mundo já está usando o Spark 3.3+, mas se você já está, use isso. É mais limpo, mais rápido e evita o problema da “morte por encadeamento”.
Exemplo completo do PySpark com Column()
Digamos que você esteja trabalhando com dados de atividade do usuário para uma plataforma baseada em assinatura. Seu DataFrame bruto fica mais ou menos assim:
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("withColumn-demo").getOrCreate()
data = [
("Alice", "NY", 24, 129.99),
("Bob", "CA", 31, 199.95),
("Charlie", "TX", 45, 0.0),
("Diana", "WA", 17, 19.99)
]
columns = ["name", "state", "age", "purchase_amount"]
df = spark.createDataFrame(data, columns)
Você tem nomes, estados, idades e quanto eles gastaram. Bastante básico. Mas, na vida real, isso nunca é suficiente. Então, é isso que vamos fazer a seguir:
- Adicione uma coluna constante para a data de ingestão.
- Crie uma nova coluna que mostre se o usuário é adulto.
- Formate
purchase_amount
com duas casas decimais. - Classifique os usuários por nível de gastos.
- Use uma função personalizada para rotular usuários.
- Use
withColumns()
para encapsular valores extras de uma maneira mais limpa.
Preparando-se para a sua próxima entrevista? O artigo “ As 36 principais perguntas e respostas para entrevistas sobre PySpark em 2025” traz um guia completo com perguntas e respostas para entrevistas sobre PySpark, cobrindo desde conceitos básicos até técnicas avançadas e estratégias de otimização.
Passo 1: Adicionar uma data de ingestão constante
É uma boa ideia programar quando os dados são inseridos no seu sistema.
from pyspark.sql.functions import lit
df = df.withColumn("ingest_date", lit("2025-07-29"))
Passo 2: Sinalizar adultos vs. menores
Você poderia ter usado só col("age") >= 18
, mas colocar isso dentro de when()
te dá controle total se a lógica ficar mais complicada.
from pyspark.sql.functions import when, col
df = df.withColumn(
"is_adult",
when(col("age") >= 18, True).otherwise(False)
)
Passo 3: Format purchase_amount
A conversão de tipos é uma das tarefas de limpeza mais frequentes que você vai fazer, principalmente ao ler arquivos CSV ou JSON.
df = df.withColumn("purchase_amount", col("purchase_amount").cast("decimal(10,2)"))
Passo 4: Classifique o nível de gastos
Digamos que você queira três grupos: “nenhum”, “baixo” e “alto”.
df = df.withColumn(
"spend_category",
when(col("purchase_amount") == 0, "none")
.when(col("purchase_amount") < 100, "low")
.otherwise("high")
)
Isso ajuda você a segmentar usuários sem precisar fazer uma consulta separada.
Passo 5: Identificar usuários usando uma função definida pelo usuário (UDF)
Agora, uma regra inventada. Digamos que você rotule uma pessoa com base no comprimento do nome dela.
from pyspark.sql.functions import udf
from pyspark.sql.types import StringType
def user_label(name):
return "simple" if len(name) <= 4 else "complex"
label_udf = udf(user_label, StringType())
df = df.withColumn("label", label_udf(col("name")))
Passo 6: Adicione várias colunas extras de uma só vez
Talvez você queira mais algumas informações, como a idade em meses e uma mensagem de boas-vindas.
df = df.withColumns({
"age_in_months": col("age") * 12,
"welcome_msg": col("name") + lit(", welcome aboard!")
})
Muito mais limpo do que chamar withColumn()
duas vezes.
Aqui está como o DataFrame final fica quando você o exibe:
df.show(truncate=False)
nome |
estado |
idade |
purchase_amount |
ingest_date |
is_adult |
categoria_de_despesa |
rótulo |
idade_em_meses |
welcome_msg |
Alice |
NY |
24 |
129,99 |
2025-07-29 |
Verdadeiro |
alto |
complexo |
288 |
Alice, seja bem-vinda a bordo! |
Bob |
CA |
31 |
199,95 |
2025-07-29 |
Verdadeiro |
alto |
simples |
372 |
Bob, seja bem-vindo a bordo! |
Charlie |
TX |
45 |
0,00 |
2025-07-29 |
Verdadeiro |
nenhum |
complexo |
540 |
Charlie, seja bem-vindo a bordo! |
Diana |
WA |
17 |
19,99 |
2025-07-29 |
Falso |
baixo |
complexo |
204 |
Diana, seja bem-vinda a bordo! |
Esse tipo de pilha de transformação é comum em engenharia de recursos, relatórios ou limpeza de feeds de terceiros.
Aprenda o básico sobre como trabalhar com big data usando o PySpark no nosso curso Fundamentos de Big Data com PySpark .
Melhores práticas e armadilhas do withColumn()
O comando ` withColumn()
` do PySpark pode parecer simples, mas pode confundir até mesmo engenheiros experientes se você não tomar cuidado. Aqui estão alguns fatores que podem prejudicar discretamente seu pipeline, além de alguns hábitos que podem evitar surpresas desagradáveis.
Sempre reatribua o resultado
Isso é básico, mas ainda pega as pessoas de surpresa: withColumn()
não mexe no seu DataFrame original. Ele te dá um novo. Se você esquecer de reatribuir, sua alteração vai sumir.
df.withColumn("new_col", lit(1)) # This won't do anything
df = df.withColumn("new_col", lit(1)) # This works
Cuidado com sobrescritas acidentais
Digamos que seu DataFrame tenha uma coluna chamada status. Você executa isto:
df = df.withColumn("Status", lit("Active"))
Parece inofensivo, né? Mas o Spark trata os nomes das colunas como insensíveis a maiúsculas e minúsculas por padrão. Isso quer dizer que você acabou de sobrescrever sua coluna de status original. Sem perceber.
Uma solução é sempre verificar df.columns
antes e depois. Ou, se o seu pipeline suportar, ative a distinção entre maiúsculas e minúsculas usando:
spark.conf.set("spark.sql.caseSensitive", "true")
Não use literais Python em expressões
Esse é fácil de esquecer. Ao adicionar constantes, evite valores Python brutos. Sempre embrulhe-os com lit()
.
df = df.withColumn("region", "US") # Bad
df = df.withColumn("region", lit("US")) # Good
Por quê? Porque withColumn()
espera uma expressão Column, não um valor bruto. Se você cometer um erro, o Spark pode mostrar uma mensagem de erro inútil ou, pior ainda, quebrar silenciosamente a lógica a jusante.
Lidar com exceções fora de withColumn()
Às vezes, as pessoas são criativas e colocam blocos inteiros de ` withColumn()
` dentro de `try/except`. É melhor isolar as partes arriscadas (como UDFs ou leituras de dados) e capturar as exceções ali. Mantenha sua camada de transformação limpa e previsível.
try:
def risky_udf(x):
if not x:
raise ValueError("Empty input")
return x.lower()
except Exception as e:
print("Error in UDF definition:", e)
Deixe o Spark falhar logo no início, não o esconda atrás de blocos try aninhados.
Saiba mais sobre exceções em Python no nosso tutorial Tratamento de exceções e erros em Python.
Prefira os built-ins em vez das UDFs
Claro, as UDFs dão poder a você. Mas eles têm suas desvantagens: desempenho mais lento, depuração mais difícil e menos otimização. Se tiver uma função embutida que faça o trabalho, use-a.
Isso:
df = df.withColumn("upper_name", upper(col("name")))
É bem mais rápido do que isso:
df = df.withColumn("upper_name", udf(lambda x: x.upper(), StringType())(col("name")))
Quando não usar com a coluna()
Mesmo sendo super flexível, o withColumn()
às vezes não é a ferramenta ideal pra tarefa.
Você está reformulando várias colunas de uma vez só.
Se você se pegar dizendo “ withColumn()
” dez vezes seguidas, é hora de mudar de estratégia. Use select()
em vez disso e escreva suas transformações como parte de uma nova projeção.
df = df.select(
col("name"),
col("age"),
(col("salary") * 0.15).alias("bonus"),
(col("score") + 10).alias("adjusted_score")
)
É mais claro, tem um desempenho melhor e faz com que o otimizador do Spark trabalhe a seu favor, em vez de contra você.
Você quer escrever lógica no estilo SQL
Se sua equipe usa bastante SQL e você já registrou o DataFrame como uma visualização temporária, muitas vezes é mais simples só executar uma consulta SQL.
df.createOrReplaceTempView("users")
df2 = spark.sql("""
SELECT name, age,
CASE WHEN age >= 18 THEN true ELSE false END AS is_adult
FROM users
""")
Isso pode ser mais fácil para analistas ou equipes com experiência em SQL que trabalham tanto com Spark quanto com bancos de dados tradicionais.
Desenvolva suas habilidades em SQL com cursos interativos, programas e projetos criados por especialistas do mundo real usando nossos cursos de SQL.
Você já está no Spark 3.3+
Se você estiver usando o Spark 3.3 ou mais recente e precisar adicionar várias colunas, o withColumns()
é seu amigo. Não é só prático, mas também pode ser mais rápido por criar uma única atualização do plano lógico.
Aprenda a implementar gerenciamento de dados distribuídos e machine learning no Spark usando o pacote PySpark do nosso curso Fundamentos do PySpark.
Conclusão
A função ` withColumn()
` do PySpark é uma das ferramentas mais versáteis no seu arsenal de transformação de dados, permitindo adicionar, modificar e criar recursos diretamente em um fluxo de trabalho centrado no DataFrame. Desde tipos de conversão e constantes de injeção até a incorporação de lógica complexa com condicionais e UDFs, o withColumn()
ajuda você a transformar dados desorganizados em pipelines prontos para produção.
Mas com esse poder vem a responsabilidade. Usar demais o withColumn()
em cadeias longas pode prejudicar o desempenho sem você perceber, enchendo o plano lógico e dificultando a otimização e a depuração dos seus trabalhos no Spark. É por isso que saber quando usar select()
, withColumns()
ou até mesmo SQL pode fazer a diferença entre um trabalho que vai devagar e um que cresce.
Com o Spark sempre mudando, principalmente com recursos como o “ withColumns()
” no Spark 3.3+, entender como cada método funciona por dentro e as vantagens e desvantagens de desempenho é essencial pra escrever um código mais limpo, rápido e fácil de manter.
Domine as técnicas por trás das transformações de colunas em grande escala, evite as armadilhas da inflação de planos e aprenda como os profissionais otimizam pipelines de recursos em nosso curso Engenharia de Recursos com PySpark .
Perguntas frequentes sobre PySpark withColumn()
Por que meu trabalho no Spark fica lento quando uso muito o withColumn()?
Quando você encadeia várias chamadas withColumn()
, o Spark adiciona cada uma delas como uma etapa separada no plano de execução lógico. Com o tempo, isso pode virar um plano inchado, mais difícil de otimizar e mais lento de executar. Em vez de empilhar dez chamadas withColumn()
, tente criar suas novas colunas dentro de uma única chamada select()
ou use withColumns()
para adicionar várias colunas de uma só vez.
Posso usar o withColumn() pra tirar uma coluna?
Não, o comando ` withColumn()
` só adiciona ou substitui colunas, não as exclui. Se você quiser excluir uma coluna, use drop()
. Você também pode usar select()
para manter só as colunas que precisa.
Por que recebo um erro quando tento usar uma string ou um número em withColumn()?
Isso geralmente acontece quando você passa um valor Python bruto em vez de envolvê-lo com um lit()
.withColumn()
espera uma expressão Spark Column. Aqui está a maneira certa:
from pyspark.sql.functions import lit
df = df.withColumn("new_col", lit(42))
