DEV Community

Jesus Oviedo Riquelme
Jesus Oviedo Riquelme

Posted on

MLZC25-09. Preparación de Datos: La Fundación de Todo Modelo Exitoso

🎯 Objetivo del Post: Aprenderás las técnicas esenciales de limpieza y preparación de datos, que representan el 80% del trabajo en cualquier proyecto de Machine Learning exitoso.

🧹 ¿Por qué la Preparación de Datos es CRÍTICA?

Imagina que estás entrenando a alguien para reconocer gatos. Si le muestras fotos borrosas, con etiquetas incorrectas, o con información faltante, ¿crees que aprendería bien? Exactamente lo mismo sucede con Machine Learning.

💡 Dato Clave: Los datos son el alimento de los algoritmos de ML. Un modelo solo puede ser tan bueno como los datos que consume.

La preparación de datos puede representar hasta el 80% del tiempo total en un proyecto de Machine Learning. Es la diferencia entre un modelo que funciona y uno que no.

🔧 ¿Qué es la Preparación de Datos?

La preparación de datos es el proceso de limpiar, transformar y organizar datos sin procesar para que sean útiles para el entrenamiento de modelos de Machine Learning.

Analogía Culinaria: Es como preparar ingredientes antes de cocinar un platillo gourmet. Necesitas lavar, cortar, marinar y organizar todo antes de empezar a cocinar.

🏗️ Los 4 Pilares Fundamentales

  1. 🧽 Limpieza: Eliminar errores, inconsistencias y datos corruptos
  2. 🔄 Transformación: Convertir datos al formato correcto para el algoritmo
  3. 🔗 Integración: Combinar datos de diferentes fuentes de manera coherente
  4. 📉 Reducción: Simplificar datos manteniendo la información más importante

⚠️ Problemas Comunes en Datos del Mundo Real

Realidad del ML: Los datos perfectos no existen. Siempre encontrarás problemas que debes resolver.

🕳️ 1. Valores Faltantes (Missing Values)

Los datos faltantes son el problema #1 en cualquier dataset real. En nuestro dataset de autos, podríamos encontrar:

Make     | Model     | Year | MSRP      | Engine HP
---------|-----------|------|-----------|------------
Toyota   | Corolla   | 2020 | $15,000   | 169
Honda    | Civic     | 2019 | $12,000   | ?
BMW      | ?         | 2021 | $25,000   | 255
Enter fullscreen mode Exit fullscreen mode

🔍 ¿Por qué faltan datos?

  • Información no disponible en la fuente original
  • Errores en la recolección de datos
  • Especificaciones técnicas no reportadas por el fabricante
  • Problemas de integridad en bases de datos

Estrategias para manejar valores faltantes:

A) Eliminar Filas con Datos Faltantes

# Eliminar filas donde cualquier columna tenga valores faltantes
df_limpio = df.dropna()
Enter fullscreen mode Exit fullscreen mode

Ventajas: Simple y rápido
Desventajas: Puede perder mucha información útil

B) Imputación (Llenar con valores estimados)

# Llenar con la media
df['Engine HP'].fillna(df['Engine HP'].mean(), inplace=True)

# Llenar con la mediana (mejor para datos con outliers)
df['Engine HP'].fillna(df['Engine HP'].median(), inplace=True)

# Llenar con el valor más frecuente
df['Make'].fillna(df['Make'].mode()[0], inplace=True)
Enter fullscreen mode Exit fullscreen mode

C) Imputación Avanzada

Usar otros datos para predecir el valor faltante:

  • Para Engine HP faltante: usar Make, Year y Engine Cylinders para estimar
  • Para MSRP faltante: usar características similares del mismo Make y Year

2. Valores Atípicos (Outliers)

Los outliers son valores que se alejan mucho del patrón normal. En datos de autos:

MSRP normales: $10,000 - $50,000
Outlier: $150,000 (auto de lujo exótico)
Outlier: $5,000 (auto muy antiguo o dañado)
Enter fullscreen mode Exit fullscreen mode

¿Cómo detectar outliers?

Método 1: Regla del 1.5 × IQR

Q1 = df['MSRP'].quantile(0.25)
Q3 = df['MSRP'].quantile(0.75)
IQR = Q3 - Q1
limite_inferior = Q1 - 1.5 * IQR
limite_superior = Q3 + 1.5 * IQR
Enter fullscreen mode Exit fullscreen mode

Método 2: Puntuación Z

Valores con |z-score| > 3 se consideran outliers

¿Qué hacer con outliers?

  • Mantener: Si representan casos legítimos (autos de lujo)
  • Eliminar: Si son errores de datos
  • Transformar: Usar logaritmos para reducir el impacto

3. Inconsistencias en Formato

Los datos pueden venir en formatos inconsistentes:

Fechas: "2020-01-15", "15/01/2020", "Enero 15, 2020"
Precios: "$15,000", "15000", "15,000.00"
Texto: "BMW", "bmw", "Bmw", "BMW "
Enter fullscreen mode Exit fullscreen mode

Soluciones:

# Estandarizar texto
df['Make'] = df['Make'].str.upper().str.strip()

# Convertir precios a numérico (MSRP ya está en formato numérico)
# df['MSRP'] ya es numérico en nuestro dataset

# Estandarizar nombres de modelos
df['Model'] = df['Model'].str.title().str.strip()
Enter fullscreen mode Exit fullscreen mode

Proceso Paso a Paso para Nuestro Dataset de Autos

Paso 1: Carga y Exploración Inicial

import pandas as pd
import numpy as np

# Cargar datos del dataset de clase
url = "https://raw.githubusercontent.com/alexeygrigorev/mlbookcamp-code/refs/heads/master/chapter-02-car-price/data.csv"
df = pd.read_csv(url)

# Exploración básica
print("Forma del dataset:", df.shape)
print("\nPrimeras 5 filas:")
print(df.head())
print("\nInformación del dataset:")
print(df.info())
print("\nEstadísticas descriptivas:")
print(df.describe())
Enter fullscreen mode Exit fullscreen mode

Paso 2: Identificar Problemas

# Valores faltantes
print("Valores faltantes por columna:")
print(df.isnull().sum())

# Tipos de datos
print("\nTipos de datos:")
print(df.dtypes)

# Valores únicos en columnas categóricas
print("\nValores únicos en Make:")
print(df['Make'].value_counts())
Enter fullscreen mode Exit fullscreen mode

Paso 3: Limpieza de Datos

A) Manejar Valores Faltantes

# Para Engine HP: usar mediana por Make y Year
df['Engine HP'] = df.groupby(['Make', 'Year'])['Engine HP'].transform(
    lambda x: x.fillna(x.median())
)

# Para variables categóricas: usar moda
df['Transmission Type'] = df['Transmission Type'].fillna(df['Transmission Type'].mode()[0])

# Eliminar filas con MSRP faltante (nuestra variable objetivo)
df = df.dropna(subset=['MSRP'])
Enter fullscreen mode Exit fullscreen mode

B) Limpiar Outliers

# Detectar outliers en MSRP usando IQR
Q1 = df['MSRP'].quantile(0.25)
Q3 = df['MSRP'].quantile(0.75)
IQR = Q3 - Q1
limite_inferior = Q1 - 1.5 * IQR
limite_superior = Q3 + 1.5 * IQR

# Filtrar outliers
df_limpio = df[(df['MSRP'] >= limite_inferior) & (df['MSRP'] <= limite_superior)]
Enter fullscreen mode Exit fullscreen mode

C) Estandarizar Formatos

# Estandarizar texto
df['Make'] = df['Make'].str.upper().str.strip()
df['Model'] = df['Model'].str.title().str.strip()

# MSRP ya está en formato numérico en nuestro dataset
# No necesitamos limpiar precios

# Convertir Engine HP a numérico si es necesario
df['Engine HP'] = pd.to_numeric(df['Engine HP'], errors='coerce')
Enter fullscreen mode Exit fullscreen mode

Paso 4: Crear Variables Derivadas

# Edad del auto
df['edad_auto'] = 2024 - df['Year']

# Categorizar por tipo de auto basado en Make
df['tipo_auto'] = df['Make'].map({
    'BMW': 'Lujo', 'MERCEDES-BENZ': 'Lujo', 'AUDI': 'Lujo',
    'TOYOTA': 'Económico', 'HONDA': 'Económico', 'NISSAN': 'Económico',
    'FORD': 'Popular', 'CHEVROLET': 'Popular'
})

# Categorizar por tamaño del motor
df['motor_grande'] = (df['Engine HP'] > 300).astype(int)
Enter fullscreen mode Exit fullscreen mode

Validación de la Preparación

Métricas de Calidad de Datos

  1. Completitud: ¿Qué porcentaje de datos no faltan?
completitud = (1 - df.isnull().sum() / len(df)) * 100
print("Completitud por columna:")
print(completitud)
Enter fullscreen mode Exit fullscreen mode
  1. Consistencia: ¿Los datos siguen reglas lógicas?
# Verificar que no hay autos del futuro
autos_futuro = df[df['Year'] > 2024]
print(f"Autos del futuro: {len(autos_futuro)}")

# Verificar que no hay Engine HP negativo
hp_negativo = df[df['Engine HP'] < 0]
print(f"Engine HP negativo: {len(hp_negativo)}")
Enter fullscreen mode Exit fullscreen mode
  1. Validez: ¿Los datos están en rangos esperados?
# Verificar rangos lógicos
print(f"MSRP: ${df['MSRP'].min():,.0f} - ${df['MSRP'].max():,.0f}")
print(f"Años: {df['Year'].min()} - {df['Year'].max()}")
print(f"Engine HP: {df['Engine HP'].min():,.0f} - {df['Engine HP'].max():,.0f}")
Enter fullscreen mode Exit fullscreen mode

Mejores Prácticas

1. Documentar Todo

# Crear un log de cambios
cambios = {
    'fecha': '2024-01-15',
    'acciones': [
        'Eliminadas 15 filas con MSRP faltante',
        'Imputado Engine HP faltante usando mediana por Make',
        'Eliminados 8 outliers en MSRP (> $100,000)',
        'Estandarizado formato de Make y Model'
    ],
    'dataset_final': f"{df.shape[0]} filas, {df.shape[1]} columnas"
}
Enter fullscreen mode Exit fullscreen mode

2. Mantener Datos Originales

Siempre guarda una copia de los datos originales:

# Guardar datos originales
df_original = df.copy()

# Guardar datos limpios
df_limpio.to_csv('car_data_limpio.csv', index=False)
Enter fullscreen mode Exit fullscreen mode

3. Crear Pipelines Reproducibles

def limpiar_datos(df):
    """Función para limpiar datos de manera reproducible"""
    df = df.copy()

    # 1. Eliminar duplicados
    df = df.drop_duplicates()

    # 2. Manejar valores faltantes
    df['Engine HP'] = df.groupby(['Make', 'Year'])['Engine HP'].transform(
        lambda x: x.fillna(x.median())
    )

    # 3. Estandarizar formato
    df['Make'] = df['Make'].str.upper().str.strip()

    # 4. Eliminar outliers
    Q1 = df['MSRP'].quantile(0.25)
    Q3 = df['MSRP'].quantile(0.75)
    IQR = Q3 - Q1
    limite_inferior = Q1 - 1.5 * IQR
    limite_superior = Q3 + 1.5 * IQR
    df = df[(df['MSRP'] >= limite_inferior) & (df['MSRP'] <= limite_superior)]

    return df
Enter fullscreen mode Exit fullscreen mode

Errores Comunes a Evitar

1. Fuga de Datos (Data Leakage)

No usar información del futuro para predecir el pasado. Por ejemplo, no usar el precio promedio de 2024 para predecir precios de 2020.

2. Sesgo de Muestreo

Asegurarse de que los datos representen la población real. Si solo tenemos datos de autos de lujo, nuestro modelo no funcionará bien con autos económicos.

3. Sobre-limpieza

No eliminar demasiados datos. A veces los "outliers" son casos legítimos importantes.

Conclusión

La preparación de datos es como construir los cimientos de una casa. Sin una base sólida, todo lo que construyas encima será inestable. Los datos limpios y bien preparados son la diferencia entre un modelo que funciona y uno que no.

Recuerda:

  • Los datos sucios generan modelos sucios
  • La preparación de datos es un proceso iterativo
  • Documenta todos los cambios que hagas
  • Siempre valida la calidad de tus datos

En el siguiente post, exploraremos cómo analizar nuestros datos limpios para entender mejor los patrones y relaciones que contienen.


¿Has trabajado con datos desordenados antes? ¿Qué estrategias has usado para limpiarlos?

Top comments (0)