Executando verificação de segurança...
32

Encontrando registros iguais com nomes diferentes: como usei a Distância de Levenshtein para comparar duas bases de dados

1. Introdução

Em qualquer operação que envolva integração de dados, um problema recorrente é a duplicidade causada por grafias diferentes para a mesma entidade.

Imagine que você tenha duas bases de clientes: uma do sistema de vendas e outra do CRM. Ao tentar cruzar os registros, percebe que o mesmo cliente aparece escrito como "Maria Aparecida da Silva" em uma base e "Maria Ap. Silva" em outra.
Essa diferença impede que ferramentas de junção exata (JOIN) no SQL ou no Excel reconheçam que se trata da mesma pessoa.

Foi exatamente essa situação que encontrei em um projeto recente. A solução veio com o uso de um algoritmo clássico de ciência da computação: a Distância de Levenshtein.


2. O que é a Distância de Levenshtein

A Distância de Levenshtein é uma métrica que mede o número mínimo de operações necessárias para transformar uma string em outra.
As operações possíveis são:

  1. Inserção (adicionar um caractere)
  2. Remoção (excluir um caractere)
  3. Substituição (trocar um caractere por outro)

Exemplo simples:

  • Transformar "casa" em "caso" requer 1 substituição (a → o).
  • Transformar "kitten" em "sitting" requer 3 operações:
    • kittensitten (substituição k → s)
    • sittensittin (substituição e → i)
    • sittinsitting (inserção g)

Quanto menor a distância, mais parecidas as strings.


3. O caso prático

Contexto

  • Base A: 15.000 registros de clientes vindos do ERP.
  • Base B: 14.500 registros do CRM.
  • Coluna comparada: Nome/Razão Social.

Problemas encontrados:

  • Abreviações: “José Carlos Pereira” vs “José C. Pereira”
  • Erros de digitação: “Agropecuaria Boa Esperanca” vs “Agropec Boa Esperança”
  • Diferença de acentos, maiúsculas/minúsculas e pontuação.

4. Preparando os dados

Antes de aplicar o algoritmo, foi necessário normalizar os textos:

  • Converter para minúsculas
  • Remover acentos
  • Remover caracteres especiais
  • Reduzir múltiplos espaços

Código de exemplo (usando Python e rapidfuzz):

from rapidfuzz import process, fuzz
import pandas as pd
from unidecode import unidecode

def normalizar(s):
    return unidecode(str(s).lower().strip())

baseA = pd.read_excel("baseA.xlsx")
baseB = pd.read_excel("baseB.xlsx")

resultados = []
for nome in baseA["nome"]:
    match = process.extractOne(
        normalizar(nome),
        baseB["nome"].map(normalizar),
        scorer=fuzz.WRatio
    )
    if match:
        nome_b = baseB.iloc[match[2]]["nome"]
        score = match[1]
        resultados.append((nome, nome_b, score))

df_result = pd.DataFrame(resultados, columns=["Nome_BaseA", "Nome_BaseB", "Similaridade"])
df_result.to_csv("resultado.csv", index=False, encoding="utf-8-sig")

5. Resultados

Registros analisados: 15.000

Matches automáticos (similaridade ≥ 90%): 13.200 (88%)

Casos para revisão manual (80–89%): 1.050 (7%)

Não encontrados: 750 (5%)

Exemplos de correspondências detectadas:

Nome na Base A Nome na Base B Similaridade
Maria Aparecida da Silva Maria Ap. Silva 92%
João Batista de Souza J. B. Souza 90%
Agropecuária Boa Esperança Ltda Agropec Boa Esperanca LTDA 96%

6. Impacto no negócio

Eliminação de duplicidades e inconsistências.

Relatórios mais precisos e confiáveis.

Integração mais fluída entre ERP e CRM.

Redução significativa do trabalho manual de conferência.

7. Visualizações

Exemplo de matriz de cálculo da distância de Levenshtein:

Distribuição das similaridades encontradas no case:

8. Lições aprendidas

Pré-processamento é essencial — a qualidade do match depende muito de como os dados são limpos.

Defina um limiar — no meu caso, 90% foi um bom ponto de corte para considerar registros iguais.

Revise casos limítrofes — registros com 80–89% de similaridade merecem inspeção manual.

Documente a metodologia — isso facilita replicar o processo futuramente.

9. Conclusão

A Distância de Levenshtein é um algoritmo simples, mas extremamente útil em projetos de integração e limpeza de dados.
Quando combinada com boas práticas de pré-processamento e bibliotecas como rapidfuzz, ela se torna uma ferramenta poderosa para identificar registros equivalentes mesmo com grafias diferentes.

No meu caso, a aplicação dessa técnica resultou em bases unificadas, menos retrabalho e maior confiabilidade nas análises — algo essencial para qualquer empresa que dependa de dados precisos para tomar decisões.

Carregando publicação patrocinada...
7

Belíssimo post, muito bom. Obrigado por compartilhar.
Pra mim, esse é do tipo dos posts fazem valer muito a pena a leitura do tabnews.

Por mais que eu não precise aplicar isso nesse momento, é como se ficasse gravado em algum lugar da cabeça de que isso existe e é resolvível. Dessa forma, ao surgir o problema concreto na frente, a memória consegue ser acessada novamente de facilmente.

De garimpo em garimpo a gente vai montando a nossa mina.

Esses dias li um do amigo que estava falando sobre o algoritmo húngaro, outro dia foi do cara que fez o baita post falando sobre arquitetura de software toda dividido em tópicos com entendimento bem destrinchado, e por aí vamos. Sempre muita coisa boa.

3

Parabéns pelo post e obrigado por compartilhar sua experiência!

Tenho usado fuzzy matching para analisar um banco com vários milhões de registros, e tem sido bem interessante.

Para comparação de nomes de pessoas físicas, uma "zona segura" que adotei foi 80% de similaridade no nome completo, com o primeiro nome igual. Nos testes práticos os resultados foram praticamente inequívocos.

Depois, peguei similaridades específicas para o primeiro nome, com uma tolerância maior para o nome completo, de forma a experimentar qual seria a margem para alguma atualização massiva ou análise manual. Cheguei a 80% do primeiro nome e 60% do nome completo ainda com uma boa chance de acertar nomes abreviados e com erros de digitação.

Existem outras formas de realizar similaridade, mas mesmo com uma quantidade grande de registros o script usando rapidfuzz performou muito bem.

2

Excelente abordagem! A forma como você combinou pré-processamento com a métrica de Levenshtein e o rapidfuzz realmente mostra o poder de unir teoria e prática. Curioso como a escolha do limiar (90%) impacta o equilíbrio entre precisão e recall. Você chegou a testar outros valores para avaliar a taxa de falsos positivos/negativos?

2

Caramba! Muito interessante, me parece uma técnica muito útil, principal quando formos precisar elaborar projetos de análise de dados e machine learning, quando é essencial manter consistência nos dados. Ótimo conteúdo👏👏👏

1
1

Parabéns pelo post, e queria compartilhar também que se os dados estiverem em um postgresql ele tem a extensão pg_trgm onde vc compara a similaridade dos campos na própria instrução sql

1

Muito bom, no sistema como temos dados como documento usamos eles inicialmente depois telefone e por último limilaridade no nome. Como integramos com vários sistemas a indisponibilidade de alguns campos é comum o q faz esse algoritmo extremamente importante

1

Meus 2 cents,

Ainda nos anos 90, em um dos sistemas que trabalhei usava-se uma funcao "soundex" com padrao brasileiro (desenvolvido atraves de um TCC na UFSC, se nao me engano).

Funcionava absurdamente bem (retornava um "token" de ate 4 bytes para cada palavra - ou algo assim - e permitia a comparacao direta). Retirava conectores ("de", "dos", etc) e "tokenizava" as palavras (ate lembra o que os LLMs fazem hoje em dia).

Semelhante ao abaixo, mas com uma funcao "soundex" personalizada:

https://www.macoratti.net/sql_sdex.htm

Tem alguma coisa aqui tambem, paginas 27-35

https://www.upf.br/_uploads/Conteudo/erbd2017/anais_ERBD2017_final_pos.pdf