Como limpar e normalizar dados de texto num ETL com pandas
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
DataFramee 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âmetroregexdestr.replace()éFalsepor omissão. Indica sempreregex=Truequando 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?