import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
def detectar_outliers_iqr_otimizado(coluna, df):
"""
Detecta e visualiza outliers em uma coluna numérica usando o método IQR,
com código mais compacto e sem perda de funcionalidade.
"""
# Validações básicas (mantidas para robustez)
if coluna not in df.columns:
raise ValueError(f"A coluna '{coluna}' não existe no DataFrame.")
if not pd.api.types.is_numeric_dtype(df[coluna]):
raise TypeError(f"A coluna '{coluna}' precisa ser numérica para aplicar o método IQR.")
df_analisado = df.copy()
# Cálculo do IQR e dos limites
Q1 = df_analisado[coluna].quantile(0.25)
Q3 = df_analisado[coluna].quantile(0.75)
IQR = Q3 - Q1
limite_inferior = Q1 - 1.5 * IQR
limite_superior = Q3 + 1.5 * IQR
# Exibe os valores de cálculo
print("\n--- Análise Estatística (Cálculo IQR) ---")
print(f"Q1 (25º percentil): {Q1}")
print(f"Q3 (75º percentil): {Q3}")
print(f"IQR (Q3 - Q1): {IQR}")
print(f"Limite Superior: {limite_superior}")
print(f"Limite Inferior: {limite_inferior}")
print("------------------------------------------")
# Lógica de filtragem otimizada usando operador de negação (~)
dados_corretos = df_analisado[
(df_analisado[coluna] >= limite_inferior) & (df_analisado[coluna] <= limite_superior)
].reset_index(drop=True)
outliers = df_analisado[
~((df_analisado[coluna] >= limite_inferior) & (df_analisado[coluna] <= limite_superior))
].reset_index(drop=True)
# Estatísticas
total = len(df_analisado)
total_corretos = len(dados_corretos)
total_outliers = len(outliers)
print(f"\nAnálise da Coluna: {coluna}")
print(f"Total de dados analisados: {total}")
print(f"Total de dados corretos: {total_corretos}")
print(f"Total de outliers: {total_outliers}")
# ... (o restante do código, incluindo a impressão e os gráficos, pode ser mantido igual) ...
# Exemplo:
# print("\nTransações Corretas:")
# print(dados_corretos)
# print("\nOutliers Encontrados:")
# print(outliers)
plt.figure(figsize=(14, 6))
plt.subplot(1, 2, 1)
sns.boxplot(data=df_analisado, y=coluna)
plt.title('Boxplot com Outliers (Dados Originais)')
plt.subplot(1, 2, 2)
sns.boxplot(data=dados_corretos, y=coluna, showfliers=False)
plt.title('Boxplot sem Outliers (Visão Pura)')
plt.tight_layout()
plt.show()
return dados_corretos, outliers
if __name__ == '__main__':
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', end='2022-01-30', freq='D'),
'Local da transação': [
'São Paulo, Brasil', 'Rio de Janeiro, Brasil', 'Belo Horizonte, Brasil', 'São Paulo, Brasil',
'São Paulo, Brasil', 'Nova Iorque, EUA', 'São Paulo, Brasil', 'São Paulo, Brasil',
'São Paulo, Brasil', 'Rio de Janeiro, Brasil', 'São Paulo, Brasil', 'São Paulo, Brasil',
'São Paulo, Brasil', 'São Paulo, Brasil', 'São Paulo, Brasil', 'São Paulo, Brasil',
'Los Angeles, EUA', 'São Paulo, Brasil', 'São Paulo, Brasil', 'São Paulo, Brasil',
'São Paulo, Brasil', 'São Paulo, Brasil', 'São Paulo, Brasil', 'São Paulo, Brasil',
'São Paulo, Brasil', 'São Paulo, Brasil', 'São Paulo, Brasil', 'São Paulo, Brasil',
'Miami, EUA', 'São Paulo, Brasil'
]
})
dados_corretos, outliers = detectar_outliers_iqr_otimizado('Valor da transação', df)