Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

[Dúvida] Detecção de outliers: IQR vs Z-score vs Regra dos 3 sigmas

Olá, pessoal.

Compartilho abaixo minha solução para o Desafio: identificando fraudes, comparando três métodos de detecção de outliers demonstrados na seção "Para saber mais: formas de identificar outliers":

  1. IQR (Interquartile Range)
  2. Z-score
  3. Regra dos 3 sigmas

1. Preparando os dados

import pandas as pd
import numpy as np
import seaborn as sns

# Dados simulados
df = pd.DataFrame({
    'ID da transação': range(1, 31),
    'Valor da transação': [
        100, 200, 150, 500, 300, 913, 250, 400, 200, 150,
        200, 200, 400, 300, 150, 301, 805, 300, 400, 250,
        150, 100, 500, 600, 200, 350, 100, 250, 800, 250
    ],
    'Data da transação': pd.date_range(start='2022-01-01', periods=30, freq='D'),
    'Local da transação': ['São Paulo, Brasil'] * 27
                           + ['Nova Iorque, EUA', 'Los Angeles, EUA', 'Miami, EUA']
})

Visualização rápida (boxplot):

sns.boxplot(x=df['Valor da transação']);

IBoxplot

2. Detecção por IQR

def detecta_outliers_iqr(df: pd.DataFrame, coluna: str) -> pd.DataFrame:
    """
    Retorna as linhas em que o valor da coluna está fora
    de [Q1 - 1.5·IQR, Q3 + 1.5·IQR].
    """
    Q1 = df[coluna].quantile(0.25)
    Q3 = df[coluna].quantile(0.75)
    IQR = Q3 - Q1

    lim_inf = Q1 - 1.5 * IQR
    lim_sup = Q3 + 1.5 * IQR

    mascara = (df[coluna] < lim_inf) | (df[coluna] > lim_sup)
    return df[mascara]

Teste:

outliers_iqr = detecta_outliers_iqr(df, 'Valor da transação')
print(outliers_iqr[['ID da transação', 'Valor da transação']])

Saída (IQR):

   ID da transação  Valor da transação
5                6                 913
16              17                 805
28              29                 800

3. Detecção por Z-score

def detecta_outliers_zscore(
    df: pd.DataFrame,
    coluna: str,
    limite: float = 3.0
) -> pd.DataFrame:
    """
    Retorna as linhas com |Z-score| > limite.
    Z-score = (x - média) / desvio_padrão (populacional).
    """
    valores = df[coluna]
    z_scores = (valores - valores.mean()) / valores.std(ddof=0)
    mascara = np.abs(z_scores) > limite
    return df[mascara]

Teste com limite padrão (3.0):

outliers_z1 = detecta_outliers_zscore(df, 'Valor da transação', limite=3.0)
print("Outliers (Z-score, lim=3.0):", outliers_z1[['ID da transação', 'Valor da transação']])

Teste ajustando para 2.2 (para comparar com IQR):

outliers_z2 = detecta_outliers_zscore(df, 'Valor da transação', limite=2.2)
print("Outliers (Z-score, lim=2.2):", outliers_z2[['ID da transação', 'Valor da transação']])

Saída (Z-score, lim=2.2):

   ID da transação  Valor da transação
5                6                 913
16              17                 805
28              29                 800

4. Detecção pela Regra dos 3 sigmas

def detecta_outliers_sigma(
    df: pd.DataFrame,
    coluna: str,
    n_sigmas: float = 3.0
) -> pd.DataFrame:
    """
    Retorna as linhas em que o valor da coluna está fora
    de [média - n_sigmas·σ, média + n_sigmas·σ].
    """
    valores = df[coluna]
    media = valores.mean()
    sigma = valores.std(ddof=0)

    lim_inf = media - n_sigmas * sigma
    lim_sup = media + n_sigmas * sigma

    mascara = (valores < lim_inf) | (valores > lim_sup)
    return df[mascara]

Teste com 3 sigmas:

outliers_s3 = detecta_outliers_sigma(df, 'Valor da transação', n_sigmas=3.0)
print("Outliers (3 sigmas):", outliers_s3[['ID da transação', 'Valor da transação']])

Teste ajustando para 2.2 sigmas:

outliers_s22 = detecta_outliers_sigma(df, 'Valor da transação', n_sigmas=2.2)
print("Outliers (2.2 sigmas):", outliers_s22[['ID da transação', 'Valor da transação']])

Saída (2.2 sigmas):

   ID da transação  Valor da transação
5                6                 913
16              17                 805
28              29                 800

5. Conclusões e Pergunta

  • IQR detectou automaticamente os 3 valores mais extremos sem ajustes.
  • Z-score e Regra dos 3 sigmas exigiram reduzir o limite de 3 para 2.2 para encontrar exatamente os mesmos outliers.

Pergunta: Existe um "padrão ouro" ou guia prático para escolher qual método e quais parâmetros usar em diferentes cenários?

Abraço!

2 respostas
solução!

Olá, Carlos! Como vai?

Muito bem! Continue resolvendo os desafios e compartilhando com a comunidade Alura.

Observei que você explorou o uso de funções customizadas para detectar outliers, utilizou muito bem o IQR e Z-score para comparar estratégias e ainda compreendeu a importância do ajuste de parâmetros para tornar a detecção mais sensível ao seu contexto. Quanto à sua pergunta:

Não existe um "padrão ouro" universal para detecção de outliers, pois a escolha do método ideal depende das características estatísticas dos dados e do objetivo da análise. Deixo abaixo, algumas diretrizes mais técnicas:

  • O IQR (Interquartile Range) é mais indicado para distribuições assimétricas ou com caudas pesadas, já que não depende da média e do desvio padrão, sendo robusto a outliers extremos.

  • O Z-score e a Regra dos 3 sigmas assumem uma distribuição aproximadamente normal (gaussiana), na qual a média e o desvio padrão são medidas representativas. Nesses casos, valores com Z-score superior a ±3 (ou ajustado como no seu exemplo com ±2.2) são considerados estatisticamente anômalos.

  • Em contextos com alta dimensionalidade, grande volume de dados ou presença de outliers multivariados, métodos mais sofisticados como Isolation Forest, DBSCAN ou LOF (Local Outlier Factor) são mais adequados. Esses algoritmos consideram relações entre múltiplas variáveis e não exigem pressupostos fortes sobre a distribuição.

Como boa prática, recomenda-se sempre iniciar com uma exploração visual (histogramas, boxplots e scatterplots) para entender o comportamento dos dados e validar os resultados obtidos com múltiplos métodos.

Uma dica interessante é usar visualizações com seaborn.histplot() ou sns.displot() para entender melhor a distribuição dos dados antes de aplicar filtros. Dessa forma:

import seaborn as sns

sns.histplot(df['Valor da transação'], bins=20, kde=True)

Resultado: Um histograma com curva de densidade, facilitando a visualização de caudas e possíveis outliers.

Isso faz com que seja mais intuitivo escolher entre métodos como IQR, Z-score ou Isolation Forest.

Ícone de sugestão Para saber mais:

Sugestão de conteúdo para você mergulhar ainda mais sobre o tema:

Alguns materiais estão em inglês, mas é possível compreendê-los usando o recurso de tradução de páginas do próprio navegador.

Espero ter ajudado e fico à disposição se precisar.

Abraço e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado

Olá, Daniel.

Obrigado pelo retorno tão completo.

Agradeço também por reforçar o ponto sobre a ausência de um método "padrão ouro" na detecção de outliers.

Gostei da dica de começar com uma exploração visual. Vou incluir no meu fluxo de análise. Vou pesquisar sobre os outros métodos sugeridos.

Abraço.