8. Preparación de datos para entrenar modelos

8.1 Por qué no alcanza con "tener datos"

En Machine Learning, disponer de una tabla no significa que ya estemos listos para entrenar. Los modelos necesitan datos en un formato consistente, sin errores graves y con una separación clara entre lo que usamos para describir cada caso y lo que queremos predecir.

En la práctica, antes de entrenar solemos revisar:

  • si faltan valores;
  • si las columnas tienen el tipo correcto;
  • si la variable objetivo está bien definida;
  • si hay columnas que no sirven o generan ruido;
  • si el conjunto de entrenamiento y prueba se construye correctamente.

Gran parte del trabajo real en un proyecto de Machine Learning ocurre en esta etapa. Un modelo sofisticado no compensa datos mal preparados.

8.2 Qué significa preparar un dataset

Preparar datos es transformar una tabla inicial en una entrada útil para el algoritmo. Dependiendo del problema, esto puede incluir tareas como:

  • eliminar o completar valores faltantes;
  • separar características y etiqueta;
  • convertir texto en numeros;
  • escalar variables;
  • crear nuevas columnas útiles;
  • descartar información irrelevante.

En este tema nos concentraremos en uno de los casos más comunes y fáciles de entender: valores faltantes en variables numéricas.

8.3 Problema de ejemplo

Supongamos que queremos predecir si un estudiante aprueba un examen. Tenemos tres características:

  • horas_estudio: horas dedicadas al estudio;
  • practicas: cantidad de ejercicios resueltos;
  • asistencia: porcentaje de asistencia a clase.

La variable objetivo será aprobo, con valor 0 o 1. El detalle importante es que algunos datos faltan. Si intentamos entrenar directamente, muchos algoritmos lanzarán error.

8.4 Ejemplo completo: limpiar datos antes de entrenar

Usaremos SimpleImputer para reemplazar valores faltantes por la mediana de cada columna. Luego entrenaremos una regresión logística.

import pandas as pd
from sklearn.impute import SimpleImputer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

df = pd.DataFrame({
    "horas_estudio": [2, 3, 4, None, 6, 7, 8, 9, 10, None],
    "practicas":     [1, 2, None, 3, 4, 5, 5, 6, None, 7],
    "asistencia":    [60, 65, 70, 72, None, 80, 85, 90, 95, 88],
    "aprobo":        [0, 0, 0, 0, 1, 1, 1, 1, 1, 1]
})

print("Datos originales:")
print(df)
print("\nValores faltantes por columna:")
print(df.isnull().sum())

X = df[["horas_estudio", "practicas", "asistencia"]]
y = df["aprobo"]

imputador = SimpleImputer(strategy="median")
X_limpio = imputador.fit_transform(X)

X_train, X_test, y_train, y_test = train_test_split(
    X_limpio, y, test_size=0.3, random_state=42, stratify=y
)

modelo = LogisticRegression()
modelo.fit(X_train, y_train)

y_pred = modelo.predict(X_test)
print("\nPredicciones:", y_pred)
print("Valores reales:", y_test.values)
print("Exactitud:", accuracy_score(y_test, y_pred))

nuevo_estudiante = pd.DataFrame({
    "horas_estudio": [5],
    "practicas": [4],
    "asistencia": [78]
})

nuevo_limpio = imputador.transform(nuevo_estudiante)
prediccion = modelo.predict(nuevo_limpio)[0]
probabilidad = modelo.predict_proba(nuevo_limpio)[0, 1]

print("\nPrediccion para el nuevo estudiante:", prediccion)
print(f"Probabilidad de aprobar: {probabilidad:.3f}")

Salida resumida esperada:

Valores faltantes por columna:
horas_estudio    2
practicas        2
asistencia       1
aprobo           0

Predicciones: [...]
Valores reales: [...]
Exactitud: ...

Prediccion para el nuevo estudiante: 1
Probabilidad de aprobar: 0.6...

8.5 Explicación paso a paso

  • df = pd.DataFrame(...): crea un dataset pequeño, pero suficientemente realista para mostrar filas incompletas.
  • df.isnull().sum(): cuenta cuántos valores faltan en cada columna. Esta revisión conviene hacerla siempre.
  • X: contiene solo las características.
  • y: contiene la variable objetivo, es decir, si aprobo o no aprobo.
  • SimpleImputer(strategy="median"): reemplaza los faltantes usando la mediana de cada columna. La mediana es útil porque resiste mejor valores extremos que el promedio.
  • fit_transform(X): aprende las medianas a partir de los datos y devuelve la versión limpia.
  • train_test_split(...): separa entrenamiento y prueba.
  • LogisticRegression(): entrena un clasificador binario con los datos ya preparados.
  • imputador.transform(nuevo_estudiante): aplica exactamente la misma transformación a datos nuevos. Esto es clave: lo que hacemos en entrenamiento debe repetirse igual al predecir.

8.6 Por qué primero limpiamos y después entrenamos

Los algoritmos esperan entradas numéricas completas y coherentes. Si una fila tiene valores faltantes, el modelo no sabe cómo interpretarla. Por eso la limpieza ocurre antes del entrenamiento.

En este ejemplo la solución fue imputar con la mediana, pero esa no es la única opción. Según el problema, también podríamos:

  • eliminar filas con demasiados faltantes;
  • usar el promedio;
  • usar el valor más frecuente;
  • reemplazar con una constante;
  • crear una columna extra que indique si faltaba el dato.

La técnica correcta depende del contexto y del significado real de la variable.

8.7 Error frecuente: limpiar distinto los datos nuevos

Uno de los errores más comunes es limpiar el conjunto de entrenamiento de una forma y luego tratar los datos nuevos de otra forma diferente. Eso rompe la coherencia del modelo.

La regla practica es simple:

  • aprender la transformación con los datos de entrenamiento;
  • guardar esa transformación;
  • aplicarla después a prueba y a datos nuevos sin recalcularla de otra manera.

Más adelante veremos que Pipeline ayuda justamente a evitar este tipo de errores.

8.8 Qué deberías observar al revisar datos

Antes de entrenar cualquier modelo, conviene revisar al menos estos puntos:

  • cantidad de filas y columnas;
  • si existen nulos;
  • si las variables numéricas tienen rangos razonables;
  • si la variable objetivo está bien cargada;
  • si hay columnas que no deberian entrar al modelo.

Este chequeo rápido evita muchos errores y hace más fácil entender por qué un modelo funciona bien o mal.

8.9 Ideas principales del tema

  • Preparar datos es una parte esencial del trabajo en Machine Learning.
  • Los valores faltantes deben tratarse antes de entrenar.
  • SimpleImputer ofrece una forma simple y segura de completar datos numericos.
  • La misma transformación aplicada al entrenamiento debe repetirse en prueba y en nuevos casos.
  • Un modelo correcto necesita datos correctos; no alcanza con elegir un buen algoritmo.