Verificando acesso...

Início / Trilha 2 — Dicas e Procedimentos Técnicos / Módulo 2.2
MÓDULO 2.2

📋 A Regra das 100 Linhas — Amostragem que Revela Tudo

100 linhas escolhidas corretamente revelam 80% dos problemas de um dataset com milhões de registros. Aprenda a técnica de amostragem estratificada e o que procurar em cada linha.

6
Tópicos
30
Minutos
Inter.
Nível
Técnico
Tipo
Regra das 100 Linhas
1

🎯 Por que 100 linhas e não 10 ou 1.000

100 linhas é o sweet spot empírico que engenheiros de dados experientes convergem após anos de prática. Grande o suficiente para capturar anomalias raras. Pequeno o suficiente para ser lido com atenção em menos de 10 minutos.

10

linhas — Insuficiente

Anomalias com frequência de 1:50 passam invisíveis. Você vê o "normal" e nunca os casos extremos que vão quebrar o pipeline.

100

linhas — Ideal ✓

Captura anomalias com frequência 1:50 ou maior. Cabe em uma tela. O cérebro humano processa sem sobrecarga em ~8 minutos.

1.000

linhas — Overkill

Custo cognitivo alto demais. A atenção cai após as primeiras 200 linhas. Você lê mais mas detecta proporcionalmente menos.

💡 A Matemática por Trás

Se um problema ocorre em 1% dos registros (1 em 100), você tem 63% de chance de detectá-lo em uma amostra aleatória de 100 linhas. Com 10 linhas, essa chance cai para apenas 9.5%. Com 1.000 linhas, sobe para 99.99% — mas você não precisa de mais de 63% de chance para iniciar a investigação.

2

📋 Como Amostrar Corretamente

A amostragem estratificada em 3 camadas garante cobertura das regiões mais problemáticas do dataset. Um sample(100) puramente aleatório tende a pegar apenas o "centro" da distribuição e miss as bordas onde estão a maioria das anomalias.

A

Camada 1 — Topo: 30 linhas (df.head(30))

Os primeiros registros costumam ser os mais antigos ou os importados primeiro.

O topo revela: formato de dados antigos antes de migrações, registros de teste ainda na produção, valores de inicialização do sistema (ex: "admin", "test@test.com"), e o comportamento original do sistema antes de mudanças de produto.

B

Camada 2 — Meio Aleatório: 40 linhas (df.sample(40, random_state=42))

Registros representativos do comportamento normal do sistema.

O meio aleatório revela: o padrão "típico" dos dados que vai ser a maioria no pipeline, formatos que funcionam corretamente, e a distribuição real de valores em condições normais.

C

Camada 3 — Bordas Estranhas: 30 linhas (df.nlargest + df.nsmallest)

Os valores mais extremos da coluna principal de valor/data.

As bordas revelam: outliers legítimos vs erros de dado, valores impossíveis ($-500, datas em 2099), registros que vão causar divisão por zero ou overflow, e o range real dos dados vs o range declarado no schema.

Código Python — Amostragem Estratificada

import pandas as pd

df = pd.read_csv('dados.csv')
coluna_valor = 'revenue'

# 3 camadas
topo = df.head(30)
meio = df.sample(40, random_state=42)
bordas = pd.concat([
    df.nlargest(15, coluna_valor),
    df.nsmallest(15, coluna_valor)
])

# Snippet final
snippet = pd.concat([topo, meio, bordas]).drop_duplicates()
snippet.to_csv('snippets/snippet_100.csv', index=False)
print(f"Snippet salvo: {len(snippet)} linhas únicas")
3

🔍 O que Procurar nas 100 Linhas

Inspecionar sem saber o que procurar é perder tempo. O checklist de 6 categorias abaixo garante que você não vai perder nenhuma categoria clássica de problema antes de iniciar o pipeline.

Checklist de Inspeção

1.
Duplicatas:

Linhas idênticas ou quase-idênticas (mesmo ID, datas ligeiramente diferentes)

2.
NAs reais vs strings:

"null", "N/A", "None", "-", " " (espaço) que pandas não detecta automaticamente

3.
Tipos misturados:

"1.500,00" e "1500.00" na mesma coluna numérica

4.
Valores hard-coded:

"TBD", "0", "999", "admin@empresa.com" como placeholder

5.
Formatos de data:

DD/MM/YYYY, YYYY-MM-DD, Unix timestamp, "15 jan 2025" na mesma coluna

6.
Estruturas embutidas:

JSON, XML, ou listas dentro de células de texto

4

💥 Casos Reais de Anomalias Encontradas

Esses casos parecem improváveis até você os encontrar pela primeira vez. Conhecer os padrões comuns transforma o diagnóstico de horas em minutos.

💱

Moedas Misturadas na Coluna "Valor"

A coluna "revenue" continha EUR, USD, JPY e INR sem indicação de qual era qual. As linhas com JPY tinham valores 150x maiores que USD — o pipeline calculava uma "receita total" que era matematicamente impossível. Detectado na linha 47 do snippet.

Solução: Criar coluna "currency" separada e coluna "revenue_usd" com conversão explícita.

📦

JSON Embutido em Célula de Texto

A coluna "description" do Stripe continha strings como {"client_id":"cus_123","plan":"enterprise","mrr":4500}. O MRR de cada cliente estava preso dentro de um JSON que o pandas lia como texto opaco. Detectado nas primeiras 30 linhas do topo.

Solução: df['description'].apply(json.loads) para extrair os campos em colunas separadas.

📅

Três Formatos de Data na Mesma Coluna

Coluna "transaction_date": algumas linhas com "2025-01-15" (ISO), outras com "15/01/2025" (BR), outras com "1736899200" (Unix timestamp). pd.to_datetime() sem format explícito inferia errado e invertia dia/mês silenciosamente para datas ambíguas como "01/12/2025".

Solução: Detectar o formato por regex e aplicar conversão específica para cada padrão.

⚠️

Idades Negativas por Bug de Migração

A coluna "client_age_days" tinha valores de -45 e -112 nas bordas inferiores do snippet. A causa: a data de criação de alguns clientes tinha sido sobrescrita com uma data de migração futura durante uma atualização em batch. Detectado nas 15 menores linhas (nsmallest).

Solução: Filtro de sanidade (age_days >= 0) com auditoria dos registros negativos antes de corrigir.

🔢

Separador Decimal Inconsistente

Coluna "amount": 70% das linhas usavam ponto como separador decimal ("1500.50"), 30% usavam vírgula ("1500,50"). pd.read_csv() lia as linhas com vírgula como string. A soma ficava 30% menor que o real. Detectado na camada aleatória do meio.

Solução: Detectar o padrão com regex e usar pd.read_csv(decimal=',') ou normalizar antes de converter.

5

📈 Quando Escalar para 1.000 ou 10.000 Linhas

100 linhas é o ponto de partida, não o ponto final. Existem três critérios claros para expandir a amostra — e ignorar esses critérios em datasets simples é desperdício de tempo.

Quando expandir a amostra

Alta Cardinalidade (> 1.000 categorias únicas)

Se a coluna "client_name" tem 5.000 valores únicos, uma amostra de 100 cobre apenas 2%. Para detectar duplicatas fuzzy (nomes quase-iguais), você precisa de pelo menos 500-1.000 linhas.

Sazonalidade Forte (diária/semanal/mensal)

Se o negócio tem picos de sexta-feira ou final de mês, 100 linhas aleatórias podem não cobrir esses períodos. Escale para 1.000 e amostre por período para garantir representatividade temporal.

Análise Estatística com Potência Necessária

Para comparar dois grupos (ex: clientes enterprise vs SMB) e detectar diferenças de 10% com 80% de potência, você precisa de N mínimo calculado via power analysis — tipicamente 200-500 por grupo.

Regra de ouro para decidir

Comece com 100 linhas sempre. Se após a inspeção você identificar um problema que requer validação em escala maior (ex: "parece que há datas invertidas apenas em registros pré-2023"), então expanda para 1.000 focando no subconjunto problemático.

Nunca expanda por precaução — expanda por evidência.

6

🔒 Protegendo PII na Amostra

Antes de enviar qualquer amostra para análise por agentes de IA, você precisa mascarar ou remover PII (Personally Identifiable Information). Uma linha de código protege você legalmente e protege seus clientes.

⚠️ O que é PII

  • Nome completo de pessoas físicas
  • Endereço de email individual
  • CPF, CNPJ, número de documento
  • Número de telefone
  • Endereço físico
  • Dados financeiros associados a um indivíduo

Código Python — Mascaramento de PII

from faker import Faker
import hashlib

fake = Faker('pt_BR')
df_safe = snippet.copy()

# Substituir nomes por nomes falsos (preserva estrutura)
df_safe['customer_name'] = [fake.name() for _ in range(len(df_safe))]

# Hash de emails (preserva unicidade para análise, remove valor real)
df_safe['email'] = df_safe['email'].apply(
    lambda x: hashlib.md5(x.encode()).hexdigest()[:12] + '@masked.com'
    if pd.notna(x) else x
)

# Remover colunas de PII direto
df_safe = df_safe.drop(columns=['cpf', 'phone', 'address'])

df_safe.to_csv('snippets/snippet_100_safe.csv', index=False)
print("PII mascarada. Seguro para compartilhar.")

✓ Técnicas de mascaramento

  • Faker para nomes e emails sintéticos
  • Hash MD5 para análise de unicidade sem valor real
  • Tokenização de IDs (ID real → token sequencial)
  • Datasets sintéticos para desenvolvimento

✗ Nunca fazer

  • Enviar CPF real para análise de IA
  • Enviar emails de clientes reais
  • Compartilhar dados financeiros identificáveis
  • Usar dados de produção em ambientes de teste

Resumo do Módulo

100 é o número certo — grande o suficiente para capturar anomalias, pequeno o suficiente para ler com atenção
Amostragem em 3 camadas — topo + meio aleatório + bordas estranhas garantem cobertura das regiões problemáticas
Checklist de 6 categorias — duplicatas, NAs reais, tipos misturados, hard-coded, datas, estruturas embutidas
Casos reais documentados — moedas misturadas, JSON embutido, datas em 3 formatos, idades negativas, decimais inconsistentes
Expanda por evidência — só escale para 1.000+ linhas quando a inspeção de 100 revelar problema que requer validação em escala
PII sempre mascarada — faker + hash para compartilhar com segurança com agentes de IA

Próximo Módulo:

2.3 — De Disparado para Unificado: pipeline passo a passo do caos ao warehouse limpo