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

Como limpar e normalizar dados de texto num ETL com pandas

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

Dados de texto vindos de formulários, exportações ou APIs chegam quase sempre desalinhados: espaços a mais, maiúsculas inconsistentes, acentos e a mesma categoria escrita de várias formas. Aprender a limpar e normalizar dados de texto num ETL com pandas garante que estes valores ficam consistentes antes de serem carregados no destino, e é um dos passos que mais evita erros e duplicados a jusante. Vamos usar um exemplo simples com nomes de cidades e estados, mas a mesma abordagem serve para qualquer coluna de texto.

Pré-requisitos

  • Python 3.10 ou superior instalado.
  • A biblioteca pandas instalada (pip install pandas).
  • Conhecimentos básicos de DataFrame e de como executar um script Python.

Passo 1: Preparar dados de exemplo

Para veres o efeito de cada transformação, começa por criar um DataFrame pequeno que imita dados reais "sujos": a mesma cidade escrita de formas diferentes e um estado com maiúsculas inconsistentes. Dados assim aparecem quando várias pessoas preenchem o mesmo campo à mão ou quando se juntam ficheiros de origens diferentes.

import pandas as pd

df = pd.DataFrame({
    "cidade": ["  Lisboa ", "PORTO", "porto ", "Évora", " lisboa"],
    "estado": ["Ativo", "ativo ", "INATIVO", " Ativo", "inativo"],
})
print(df)

Repara que "Lisboa", " lisboa" e "PORTO" representam apenas duas cidades, mas o computador vê-as como valores diferentes. É isso que vamos corrigir.

Passo 2: Remover espaços a mais

O primeiro problema são os espaços no início, no fim e repetidos dentro do texto. O método str.strip() corta as pontas e str.replace() com uma expressão regular junta vários espaços num só. Aplicamos a todas as colunas de texto de uma vez.

for col in ["cidade", "estado"]:
    df[col] = df[col].str.strip()
    df[col] = df[col].str.replace(r"\s+", " ", regex=True)
Dica: a partir do pandas 2.0, o parâmetro regex de str.replace() é False por omissão. Indica sempre regex=True quando usas um padrão.

Passo 3: Uniformizar maiúsculas e minúsculas

"PORTO", "porto" e "Porto" deveriam ser o mesmo valor. Aplicamos str.title() aos nomes de cidade, para ficarem com a primeira letra maiúscula, e str.lower() ao estado, que vamos padronizar já a seguir. Usamos str.title() em vez de str.upper() porque queremos nomes legíveis, não tudo em maiúsculas.

df["cidade"] = df["cidade"].str.title()
df["estado"] = df["estado"].str.lower()

Passo 4: Remover acentos

Para criar chaves consistentes — por exemplo, para juntar tabelas por nome de cidade — convém remover os acentos. A normalização NFKD separa a letra do acento; ao codificar em ASCII ignorando o que não cabe, os acentos desaparecem e "Évora" fica "Evora".

df["cidade"] = (
    df["cidade"]
    .str.normalize("NFKD")
    .str.encode("ascii", "ignore")
    .str.decode("utf-8")
)

Passo 5: Padronizar categorias com um dicionário

Por fim, mapeamos cada variação para um rótulo oficial com um dicionário e o método map(). Um valor que não conste do dicionário fica como NaN — o que é útil, porque denuncia categorias inesperadas que ainda não trataste. Se preferires manter os valores desconhecidos em vez de os transformar em NaN, usa replace() em vez de map().

mapa_estado = {"ativo": "Ativo", "inativo": "Inativo"}
df["estado"] = df["estado"].map(mapa_estado)

Verificar o resultado

Confirma o resultado imprimindo os valores únicos de cada coluna e a contagem de valores em falta. Se a limpeza correu bem, cada cidade e cada estado aparecem escritos de uma só forma.

print(df["cidade"].unique())
print(df["estado"].unique())
print(df.isna().sum())

Deves obter ['Lisboa' 'Porto' 'Evora'] nas cidades e ['Ativo' 'Inativo'] nos estados, sem valores em falta. Se aparecer algum NaN, há uma categoria que ficou por mapear no Passo 5.

Conclusão

Com poucos métodos de pandas transformaste texto inconsistente em dados limpos e previsíveis, prontos para a fase de carregamento do teu ETL. O passo seguinte natural é reunir estas transformações numa função reutilizável e aplicá-la a cada ficheiro que processas, garantindo o mesmo tratamento em todo o pipeline. Que outra coluna do teu conjunto de dados ganharia em ser normalizada desta forma?