image

Acesso para sempre a +2.150 cursos, inglês e IA

84
%OFF

G

Ggbond10/09/2026 04:00
Share

Dados “sujos” também chegam à IA: por que limpar o dataset vem antes do modelo

  • #Python

Quando comecei a estudar análise de dados, eu tinha uma ideia meio errada sobre o processo.

Na minha cabeça, a parte realmente interessante começava quando chegávamos ao modelo: escolher um algoritmo, treinar, comparar resultados e tentar melhorar as métricas.

Limpeza de dados?

Parecia apenas aquela etapa meio chata que precisava ser feita antes da parte “de verdade”.

Só que, depois de trabalhar com alguns datasets, percebi que é praticamente o contrário.

Um modelo pode ser excelente. O código pode rodar sem nenhum erro. O notebook pode ficar bonito. Mas, se os dados de entrada estiverem errados, duplicados ou inconsistentes, a IA não vai magicamente consertar isso.

Ela simplesmente vai aprender com o que recebeu.

Um problema que aparece bastante em dados de mercado

Trabalho com a BYDFi e, por isso, dados de mercado aparecem com certa frequência no meu dia a dia. Uma coisa que aprendi trabalhando com esse tipo de informação é que receber muitos dados não significa necessariamente ter bons dados.

Antes de pensar em análise, automação ou inteligência artificial, existe uma etapa menos chamativa, mas essencial: verificar o que realmente chegou ao dataset.

Vamos imaginar um pequeno conjunto de dados de mercado:

timestamp | symbol  | price
09:00     | BTCUSDT | 58231.2
09:01     | BTCUSDT | null
09:02     | BTCUSDT | 58302.5
09:02     | BTCUSDT | 58302.5
09:03     | BTCUSDT | -1
09:04     | BTCUSDT | 58410.8

Olhando rapidamente, parece apenas uma pequena série temporal.

Mas temos pelo menos três problemas: um valor ausente, uma linha duplicada e um preço negativo que provavelmente não faz sentido nesse contexto.

Se jogarmos isso diretamente em uma análise ou modelo, estamos basicamente dizendo:

“Boa sorte. Descubra sozinho.”

E o modelo não sabe que -1 é estranho.

Para ele, -1 é apenas um número.

Primeiro passo: conhecer os dados

Com Pandas, eu normalmente começo com algo bem simples:


import pandas as pd

df = pd.read_csv("market_data.csv")

print(df.head())
print(df.info())
print(df.describe())

Nada muito sofisticado.

Mas essas três verificações já ajudam a responder algumas perguntas importantes.

Quantas linhas existem? Quais são os tipos das colunas? Existem valores ausentes? Os valores mínimos e máximos parecem razoáveis?

Antes de tentar “melhorar” um dataset, precisamos entender o que realmente existe nele.

Encontrando valores ausentes

Uma das verificações mais simples é:


print(df.isnull().sum())

Imagine que o resultado seja:

timestamp    0
symbol       0
price        1

Temos um preço ausente.

E agora?

Bom, depende.

Podemos simplesmente remover a linha:


df = df.dropna(subset=["price"])

Em outros casos, talvez faça sentido preencher o valor usando alguma estratégia:


df["price"] = df["price"].ffill()

Mas aqui existe uma armadilha importante.

Preencher um valor não significa recuperar a informação original. Estamos fazendo uma suposição.

Dependendo do problema, essa suposição pode ser aceitável ou pode alterar o resultado da análise.

Por isso, não gosto muito da ideia de simplesmente usar fillna() em tudo e seguir a vida. Primeiro precisamos entender por que aquele dado está faltando.

Dados duplicados são mais silenciosos

Duplicatas podem ser ainda mais traiçoeiras porque, visualmente, tudo parece normal.

Podemos encontrá-las assim:


duplicates = df.duplicated()

print(duplicates.sum())

E remover:


df = df.drop_duplicates()

Só que existe outro detalhe: nem toda repetição é necessariamente uma duplicata.

Imagine duas transações diferentes com o mesmo preço e registradas no mesmo segundo. Dependendo do dataset, isso pode ser perfeitamente válido.

Talvez seja melhor definir quais colunas realmente identificam uma observação:


df = df.drop_duplicates(
  subset=["timestamp", "symbol"],
  keep="first"
)

Esse é um padrão que aparece bastante em análise de dados: a ferramenta pode ser simples, mas decidir como usá-la exige entender o contexto.

E os valores impossíveis?

Agora chegamos ao nosso preço de -1.

Podemos procurar valores assim:


invalid_prices = df[df["price"] <= 0]

print(invalid_prices)

Depois, dependendo da origem e do significado dos dados, podemos removê-los:


df = df[df["price"] > 0]

Pronto?

Nem sempre.

Imagine agora esta sequência:

58231
58302
58410
999999
58390

999999 é positivo.

Não é null.

Não é uma duplicata.

Do ponto de vista do tipo de dado, aparentemente está tudo certo.

Mesmo assim, provavelmente merece uma segunda olhada.

É aí que começamos a entrar no território dos outliers.

Detectando valores fora do padrão

Uma técnica simples é usar o intervalo interquartil, o famoso IQR:


Q1 = df["price"].quantile(0.25)
Q3 = df["price"].quantile(0.75)

IQR = Q3 - Q1

lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR

outliers = df[
  (df["price"] < lower) |
  (df["price"] > upper)
]

print(outliers)

Isso ajuda a encontrar observações muito distantes da distribuição mais comum.

Mas aqui vem outra pegadinha:

outlier não significa automaticamente erro.

Em séries financeiras, sensores, tráfego de servidores ou dados de segurança, eventos extremos podem ser justamente a informação mais interessante do dataset.

Então eu prefiro pensar assim:

outlier != dado errado

Um outlier significa algo mais próximo de:

"Ei, talvez valha a pena olhar isso aqui."

A decisão de remover ou manter vem depois.

Datas também dão trabalho

Datas parecem inocentes até começarmos a trabalhar seriamente com elas.

Podemos começar convertendo a coluna:


df["timestamp"] = pd.to_datetime(
  df["timestamp"],
  errors="coerce"
)

O errors="coerce" transforma datas inválidas em NaT.

Depois podemos verificar:


print(df["timestamp"].isna().sum())

Também gosto de ordenar explicitamente:


df = df.sort_values("timestamp")

Isso é especialmente importante quando estamos trabalhando com séries temporais.

Treinar um modelo com dados fora da ordem cronológica pode produzir resultados estranhos. Dependendo de como dividimos treino e teste, podemos até criar data leakage sem perceber.

E aí acontece aquela situação meio cruel: o modelo parece ótimo no notebook, mas quando encontra dados realmente novos, a história muda.

Padronizar tipos também faz parte da limpeza

Outro problema clássico é encontrar uma coluna assim:

price
58231.2
58302.5
"58410.8"
N/A
58390.1

Parte da coluna é número, parte é texto.

Podemos normalizar:


df["price"] = pd.to_numeric(
  df["price"],
  errors="coerce"
)

Depois verificamos novamente:


print(df["price"].isnull().sum())

Esse ciclo de converter, verificar, corrigir e verificar novamente aparece o tempo todo.

Não é a parte mais glamourosa de trabalhar com dados.

Mas funciona.

Dados em tempo real trazem outro problema: idade

Existe ainda uma questão que fica particularmente importante quando trabalhamos com dados de mercado: um dado pode estar correto e ainda assim estar velho demais para a aplicação.

Imagine:

symbol: BTCUSDT
price: 58231.2
timestamp: 09:00:00

A estrutura está perfeita.

O preço é positivo.

Nenhum campo está faltando.

Mas e se agora forem 09:15?

Em alguns projetos, quinze minutos não fazem diferença. Em outros, tornam aquela observação praticamente inútil.

Esse é um detalhe que aparece bastante quando trabalho com informações de mercado relacionadas à BYDFi: validar o valor não basta. Também precisamos saber quando aquele valor foi observado.

Podemos criar uma verificação simples:


import time

current_time = int(time.time())
data_age = current_time - data["timestamp"]

if data_age > 30:
  print("Dado possivelmente desatualizado")

Os 30 segundos são apenas um exemplo.

O limite correto depende completamente da aplicação.

Só depois vem o modelo

Depois dessas etapas, nosso processo pode ficar parecido com isto:


import pandas as pd

df = pd.read_csv("market_data.csv")

df["timestamp"] = pd.to_datetime(
  df["timestamp"],
  errors="coerce"
)

df["price"] = pd.to_numeric(
  df["price"],
  errors="coerce"
)

df = df.dropna(
  subset=["timestamp", "price"]
)

df = df.drop_duplicates()

df = df[df["price"] > 0]

df = df.sort_values("timestamp")

Agora sim podemos começar a pensar em análise exploratória, criação de features ou machine learning.

Mesmo assim, isso não significa que o dataset esteja perfeito.

Significa apenas que fizemos algumas verificações antes de entregar os dados ao modelo.

IA não sabe o que você quis dizer

Essa talvez seja a parte mais importante.

Quando um modelo encontra:

price = -1

ele não pensa:

“Hmm... provavelmente aconteceu algum erro na coleta.”

Ele recebe -1.

Só isso.

Se houver milhares de problemas desse tipo, o modelo pode aprender padrões que simplesmente não existem no mundo real.

E existe uma parte ainda mais perigosa: o código pode continuar funcionando normalmente.

Nenhuma exceção.

Nenhuma tela vermelha.

Nenhum erro de sintaxe.

Apenas um resultado ruim sendo construído silenciosamente em cima de dados ruins.

O que eu verifico antes de pensar no modelo

Hoje, antes de começar a brincar com algoritmos, tento responder algumas perguntas:

  1. Existem valores ausentes?
  2. Existem registros duplicados?
  3. Os tipos das colunas estão corretos?
  4. Existem valores impossíveis?
  5. Existem outliers que precisam ser investigados?
  6. As datas estão corretas e ordenadas?
  7. As unidades são consistentes?
  8. Os dados estão suficientemente atualizados?
  9. Existe risco de data leakage?

Não é uma checklist perfeita.

Mas já evita muita dor de cabeça.

No começo, limpar dados parecia ser a parte menos interessante de um projeto de inteligência artificial.

Hoje penso quase o contrário.

Treinar um modelo ficou relativamente fácil. Algumas bibliotecas permitem fazer isso com poucas linhas de código.

O trabalho realmente interessante está em entender o que estamos entregando para esse modelo.

Porque existe uma frase antiga em computação que continua funcionando muito bem na era da inteligência artificial:

Garbage in, garbage out.

A IA ficou muito mais poderosa.

Os dados ruins, infelizmente, continuam ruins.

Share
Recommended for you
Bootcamp Bradesco - GenAI, Dados & Cyber
Bootcamp Afya - Automação de Dados com IA
Accenture - Python para Análise e Automação de Dados
Comments (0)