📦 MÓDULO 1: "Calidad de Datos: Tu Modelo es Tan Bueno como Tus Datos"

Objetivo:

Entender por qué el preprocesamiento no es opcional—es el núcleo de cualquier modelo exitoso de ML. Aprender a diagnosticar la salud del conjunto de datos antes de tocar cualquier algoritmo.


1.1 ¿Por qué el Preprocesamiento es el 80% del Trabajo?

"La ciencia de datos es 80% limpieza de datos, 20% quejarse por limpiar datos." — Anónimo

En el mundo real, los datos nunca llegan limpios, ordenados y listos para usar. Llegan con:

  • Valores faltantes (NaN, None, "", ?)
  • Errores tipográficos ("Madird", "Barcelonaa")
  • Valores atípicos extremos (un salario de 9999999 en una encuesta de ingresos promedio)
  • Formatos inconsistentes (fechas como "2024/05/01", "01-May-2024", "1 de mayo")
  • Variables categóricas no estandarizadas ("Sí", "si", "SI", "yes")

Consecuencia directa: Alimentar datos sucios a un modelo hace que aprenda patrones incorrectos. Basura Adentro → Basura Afuera.


1.2 Diagnóstico Inicial del Conjunto de Datos

Antes de hacer cualquier cosa, explora tu conjunto de datos como un detective.

Herramientas clave de Pandas:

import pandas as pd

# Cargar conjunto de datos
df = pd.read_csv("datos_fraude.csv")

# Vista previa rápida
print(df.head())
print(df.info())  # Tipos de datos y conteos no nulos
print(df.describe())  # Estadísticas descriptivas (solo numéricas)

# Ver valores únicos en columnas categóricas
print(df['tipo_transaccion'].unique())
print(df['pais'].value_counts())

# Verificar valores nulos
print(df.isnull().sum())

Visualización diagnóstica con Seaborn:

import seaborn as sns
import matplotlib.pyplot as plt

# Histograma de una variable numérica
sns.histplot(df['monto_transaccion'], bins=50, kde=True)
plt.title("Distribución del Monto de Transacciones")
plt.show()

# Diagrama de caja para detectar valores atípicos
sns.boxplot(x=df['monto_transaccion'])
plt.title("Diagrama de Caja: Encontrando Valores Atípicos en Montos")
plt.show()

# Gráfico de barras para variables categóricas
sns.countplot(data=df, x='tipo_tarjeta')
plt.title("Distribución de Tipos de Tarjetas")
plt.xticks(rotation=45)
plt.show()

1.3 Manejo de Valores Faltantes

¿Qué hacer con los NaN?

Opción 1: Eliminar filas o columnas

# Eliminar filas con cualquier NaN
df_clean = df.dropna()

# Eliminar columnas con más del 50% de NaN
df_clean = df.dropna(axis=1, thresh=len(df)*0.5)

⚠️ Precaución: Solo recomendable si pierdes pocos puntos de datos. Si eliminas el 30% de tus filas, tu modelo puede volverse sesgado.


Opción 2: Imputación (rellenar con valores)

from sklearn.impute import SimpleImputer

# Imputar media para variables numéricas
imputer_num = SimpleImputer(strategy='mean')
df[['edad', 'monto_transaccion']] = imputer_num.fit_transform(df[['edad', 'monto_transaccion']])

# Imputar moda para variables categóricas
imputer_cat = SimpleImputer(strategy='most_frequent')
df[['tipo_tarjeta']] = imputer_cat.fit_transform(df[['tipo_tarjeta']])

Buena práctica: Usar ColumnTransformer para aplicar diferentes estrategias a diferentes columnas (lo cubriremos en detalle en el Módulo 3).


1.4 Manejo de Valores Atípicos

¿Qué es un valor atípico?

Un valor que se desvía significativamente del resto de los datos. Puede ser:

  • Un error de entrada (ej., edad = 999)
  • Un caso real pero extremo (ej., una transacción de $1,000,000 en un conjunto de datos de compras promedio de $50)

Métodos de detección:

  • Regla del IQR (Rango Intercuartílico):
Q1 = df['monto_transaccion'].quantile(0.25)
Q3 = df['monto_transaccion'].quantile(0.75)
IQR = Q3 - Q1

limite_inferior = Q1 - 1.5 * IQR
limite_superior = Q3 + 1.5 * IQR

outliers = df[(df['monto_transaccion'] < limite_inferior) | (df['monto_transaccion'] > limite_superior)]
print(f"Valores atípicos detectados: {len(outliers)}")

¿Qué hacer con ellos?

  • Eliminarlos (si son claramente errores)
  • Limitarlos: Reemplazar con límite superior/inferior
df['monto_transaccion'] = df['monto_transaccion'].clip(lower=limite_inferior, upper=limite_superior)
  • Transformación logarítmica (si la distribución está muy sesgada)
df['log_monto'] = np.log1p(df['monto_transaccion'])  # log(1+x) para evitar log(0)

📝 Ejercicio 1.1: Diagnóstico y Limpieza

Conjunto de datos sugerido: fraud_data.csv (simulado, con columnas: user_id, monto, edad, pais, tipo_tarjeta, hora_dia, es_fraude)

Tareas:

  1. Cargar el conjunto de datos y mostrar .info() y .describe().
  2. Identificar qué columnas tienen valores faltantes y decidir cómo imputarlos (justificar tu elección).
  3. Usar un diagrama de caja para identificar valores atípicos en monto. Aplicar limitación basada en IQR.
  4. Verificar la distribución de edad. ¿Hay valores imposibles (ej., edad < 0 o > 120)? Corregirlos.
  5. Guardar el conjunto de datos limpio como fraud_clean.csv.

💡 Notas Adicionales:

  • Nunca asumas que los datos están limpios. Siempre explora primero.
  • Documenta cada cambio. Usa comentarios o celdas markdown para explicar por qué eliminaste o imputaste algo.
  • Los valores atípicos no siempre son malos. En detección de fraude, ¡el valor atípico puede ser exactamente lo que buscas!

Course Info

Course: AI-course1

Language: ES

Lesson: Module1