(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Como remover linhas duplicadas com PySpark no Databricks

João Barros 16 de July de 2026 4 min de leitura

Dados duplicados surgem por reprocessamentos, cargas repetidas ou junções mal desenhadas — e rapidamente inflacionam contagens, distorcem métricas e partem relatórios. Remover linhas duplicadas com PySpark no Databricks é uma das tarefas de limpeza mais comuns do dia a dia, e é simples quando se conhecem as funções certas. Este guia mostra, passo a passo, como identificar e eliminar duplicados, quer em todas as colunas quer apenas nas que definem um registo único. No final, guardas o resultado numa tabela Delta pronta a reutilizar.

Pré-requisitos

  • Um workspace Databricks com um cluster (ou SQL warehouse) ativo.
  • Um notebook Python anexado ao cluster.
  • Noções básicas de Python e do conceito de DataFrame.
  • A variável spark já vem disponível em qualquer notebook Databricks.

Passo 1: Criar um DataFrame de exemplo com duplicados

Para acompanhar o exemplo, começamos por criar um pequeno DataFrame. Repara que a linha do id=2 está totalmente repetida e que o id=3 aparece duas vezes com cidades diferentes — ou seja, um duplicado apenas na coluna-chave. Estes dois casos exigem estratégias diferentes, como vais ver.

from pyspark.sql import Row

dados = [
    Row(id=1, cliente="Ana",   cidade="Porto",  atualizado="2026-07-10"),
    Row(id=2, cliente="Bruno", cidade="Lisboa", atualizado="2026-07-11"),
    Row(id=2, cliente="Bruno", cidade="Lisboa", atualizado="2026-07-11"),
    Row(id=3, cliente="Rita",  cidade="Braga",  atualizado="2026-07-12"),
    Row(id=3, cliente="Rita",  cidade="Faro",   atualizado="2026-07-15"),
]

df = spark.createDataFrame(dados)
df.show()

Passo 2: Contar os duplicados antes de apagar

Antes de remover seja o que for, convém perceber quantos duplicados existem — assim confirmas o impacto da limpeza e detetas surpresas. Agrupar por todas as colunas e filtrar os grupos com mais de uma linha revela as repetições exatas. Guarda este número: no fim vais compará-lo com a contagem final para confirmar quantas linhas foram removidas.

print("Total de linhas:", df.count())

duplicados = (df.groupBy(df.columns)
                .count()
                .filter("count > 1"))
duplicados.show()

Passo 3: Remover linhas totalmente duplicadas

Quando duas linhas são iguais em todas as colunas, o método dropDuplicates() sem argumentos resolve o problema, mantendo apenas uma cópia de cada linha. O método distinct() faz exatamente o mesmo e é só uma forma mais curta de escrever. Ambos provocam um shuffle, por isso aplica-os depois de já teres filtrado colunas desnecessárias.

sem_duplicados = df.dropDuplicates()
print("Depois de dropDuplicates():", sem_duplicados.count())

# Equivalente:
sem_duplicados = df.distinct()

Passo 4: Remover duplicados por coluna-chave

Muitas vezes uma linha é considerada duplicada com base numa chave de negócio (por exemplo, o id), mesmo que as restantes colunas variem. Para esse caso, indica as colunas a considerar e o Spark deduplica só por elas.

por_chave = df.dropDuplicates(["id"])
por_chave.show()
Atenção: ao usar um subconjunto de colunas, o Spark mantém uma linha qualquer de cada grupo — não garante qual das linhas fica. Se isso for importante, usa o passo seguinte.

Passo 5: Manter o registo mais recente

Quando queres controlar qual a linha que sobrevive — por exemplo, ficar com a versão mais recente de cada id — usa uma janela (Window) com row_number(). A ideia é numerar as linhas dentro de cada grupo, ordenadas pela data descendente, e manter apenas a que recebe o número 1.

from pyspark.sql.window import Window
from pyspark.sql.functions import row_number, col

janela = Window.partitionBy("id").orderBy(col("atualizado").desc())

mais_recente = (df.withColumn("rn", row_number().over(janela))
                  .filter(col("rn") == 1)
                  .drop("rn"))
mais_recente.show()

Com esta abordagem, o id=3 fica com a cidade "Faro", por ser a atualização de 2026-07-15, e descartas a versão antiga de forma controlada.

Passo 6: Gravar o resultado numa tabela Delta

Para reutilizares os dados já limpos, guarda o DataFrame numa tabela Delta gerida. Ajusta o nome do catálogo e do schema ao teu ambiente.

(mais_recente.write
    .format("delta")
    .mode("overwrite")
    .saveAsTable("vendas.clientes_limpos"))

Verificar o resultado

Compara a contagem antes e depois e confirma que já não existe nenhuma chave repetida. Se a última consulta não devolver linhas, a limpeza correu como esperado: passaste de 5 linhas para 3 registos únicos por id.

print("Linhas originais:", df.count())
print("Linhas finais:", mais_recente.count())

(mais_recente.groupBy("id")
             .count()
             .filter("count > 1")
             .show())

Conclusão

Em poucos passos passaste de dados repetidos para um conjunto limpo e fiável: dropDuplicates() para linhas idênticas, um subconjunto de colunas para chaves de negócio e uma Window quando precisas de escolher exatamente qual registo manter. A partir daqui, podes agendar este notebook como um Job para correr automaticamente, ou combinar a lógica com MERGE INTO para deduplicar de forma incremental à medida que chegam novos dados. Qual será a coluna-chave que melhor identifica um registo único nos teus próprios dados?