tutoriales.com

Limpieza Masiva y Detección de Anomalías con NumPy y Pandas 🧹

Domina el arte de limpiar datasets complejos y detectar valores atípicos (outliers) utilizando las potentes herramientas de vectorización de NumPy y la flexibilidad de Pandas.

Intermedio8 min de lectura14 views
Reportar error

Introducción a la Odisea de los Datos Sucios 🧹

En el mundo real de la ciencia de datos, los datasets limpios y perfectamente estructurados son una rareza absoluta. Como analistas e ingenieros de datos, pasamos hasta un 80% de nuestro tiempo valioso en la fase menos glamorosa pero más crucial: la limpieza de datos. Un modelo de machine learning o un análisis estadístico es tan bueno como los datos que lo alimentan (Garbage in, garbage out).

En este tutorial exhaustivo, exploraremos cómo transformar datos caóticos, incompletos y ruidosos en información prístina utilizando la combinación definitiva de Pandas para la manipulación tabular y NumPy para el cálculo numérico ultrarrápido. Vamos a desglosar desde el manejo de valores nulos hasta la detección matemática sofisticada de anomalías.

💡 Consejo: Antes de empezar cualquier proceso de limpieza, asegúrate de guardar una copia de respaldo de tu DataFrame original utilizando el método .copy() para evitar modificar los datos crudos por accidente.

Preparación del Entorno y Dataset de Trabajo 🔬

Para poner en práctica estas técnicas, primero necesitamos configurar nuestro entorno de desarrollo e importar las librerías necesarias. Además, vamos a simular un dataset realista que contenga una variedad de problemas típicos: valores faltantes, tipos de datos incorrectos, espacios en blanco accidentales, duplicados y anomalías estadísticas.

import pandas as pd
import numpy as np

# Establecemos una semilla para reproducibilidad
np.random.seed(42)

# Simulando datos caóticos
n_filas = 1000
data = {
    "id_cliente": np.arange(100, 100 + n_filas),
    "edad": np.random.choice([np.nan, 22, 25, 30, 35, 40, 45, 50, 150, -5], n_filas, p=[0.1, 0.15, 0.15, 0.15, 0.15, 0.1, 0.1, 0.05, 0.02, 0.03]),
    "salario": np.random.normal(50000, 15000, n_filas),
    "categoria": np.random.choice(["A", "B", "C", "  A  ", "b", np.nan], n_filas),
    "fecha_registro": pd.date_range(start="2021-01-01", periods=n_filas, freq="H")
}

df = pd.DataFrame(data)
# Introducimos algunos valores atípicos extremos en salario
df.loc[np.random.choice(n_filas, 10), "salario"] = 9999999
# Introducimos filas duplicadas deliberadamente
df = pd.concat([df, df.iloc[:15]], ignore_index=True)
Datos Crudos Detección de Nulos Limpieza de Texto Detección de Outliers Dataset Limpio

Auditoría Inicial y Diagnóstico de Datos 🔍

Antes de aplicar cualquier transformación ciega, debemos auditar el DataFrame para entender la magnitud del problema. La inspección visual y cuantitativa nos guiará sobre qué estrategias implementar.

Métodos Esenciales de Inspección

Utilizaremos una combinación de métodos nativos de Pandas para evaluar la salud de nuestro dataset:

  • df.info(): Proporciona el uso de memoria y los tipos de datos por columna.
  • df.isnull().sum(): Cuantifica exactamente cuántos valores faltantes existen.
  • df.duplicated().sum(): Revela filas exactamente idénticas.
print("--- INFORMACIÓN GENERAL ---")
print(df.info())

print("\n--- VALORES FALTANTES ---")
print(df.isnull().sum())

print(
    f"\n--- FILAS DUPLICADAS: {df.duplicated().sum()} ---"
)
⚠️ Advertencia: Un valor faltante no siempre está representado por NaN o None en Pandas. A veces se oculta como cadenas vacías (""), espacios en blanco (" ") o valores numéricos centinela (como -999 o 9999).

Limpieza y Estandarización de Datos Categóricos y de Texto 📝

Los datos de texto suelen ser la fuente principal de inconsistencias. En nuestro dataset simulado, la columna categoria tiene problemas de espacios iniciales/finales y mayúsculas/minúsculas mezcladas ("A" frente a " A " o "b").

Transformación con el accessor .str

Para solucionar esto, aplicamos operaciones vectorizadas de cadenas:

# Eliminamos espacios en blanco y convertimos todo a mayúsculas
df["categoria"] = df["categoria"].str.strip().str.upper()

# Verificamos las categorías únicas resultantes
print(df["categoria"].value_counts(dropna=False))

Al ejecutar este código, unificamos " A " con "A" y "b" con "B", reduciendo drásticamente la cardinalidad fantasma creada por errores tipográficos.


Estrategias Avanzadas para el Manejo de Valores Faltantes (NaN) 🛠️

En nuestro dataset, la columna edad contiene tanto valores nulos (NaN) como valores absurdos que escapan de la lógica biológica (como -5 y 150).

Paso 1: Convertir valores lógicamente imposibles en NaN

Antes de imputar, debemos limpiar los centinelas ilógicos tratándolos como nulos estándar usando NumPy:

# Reemplazamos edades menores a 0 o mayores a 100 por NaN
df.loc[(df["edad"] < 0) | (df["edad"] > 100), "edad"] = np.nan

Paso 2: Imputación Inteligente

Dependiendo del contexto, podemos eliminar las filas con nulos (dropna) o rellenarlas (fillna). Sin embargo, utilizar la media o la mediana condicional basada en otra columna es una técnica mucho más profesional.

# Imputación utilizando la mediana global para la edad
mediana_edad = df["edad"].median()
df["edad"].fillna(mediana_edad, inplace=True)
¿Cuándo es mejor usar la Media vs. la Mediana? La media es sensible a valores extremos (outliers), por lo que si tu distribución está sesgada, la media arrastrará el valor imputado. La mediana es robusta ante valores atípicos y suele ser la opción más segura en distribuciones sesgadas.

Detección y Tratamiento de Anomalías (Outliers) con NumPy 📊

Los valores atípicos pueden distorsionar completamente los análisis estadísticos y arruinar el rendimiento de modelos predictivos. Utilizaremos dos métodos estadísticos robustos con NumPy y Pandas: el método del Rango Intercuartílico (IQR) y la puntuación Z (Z-score).

Método 1: El Rango Intercuartílico (IQR)

El IQR es excelente para distribuciones no necesariamente normales:

Q1 = df["salario"].quantile(0.25)
Q3 = df["salario"].quantile(0.75)
IQR = Q3 - Q1

# Definimos los límites para considerar un valor como outlier
limite_inferior = Q1 - 1.5 * IQR
limite_superior = Q3 + 1.5 * IQR

# Identificando outliers
outliers_iqr = df(
    (df["salario"] < limite_inferior) | (df["salario"] > limite_superior)
)
print(f"Número de outliers detectados por IQR: {outliers_iqr.sum()}")

Método 2: Puntuación Z (Z-score) con NumPy

La puntuación Z mide cuántas desviaciones estándar está un valor de la media. Es muy útil cuando asumimos una distribución aproximadamente normal:

# Calculamos el Z-score utilizando operaciones vectorizadas de NumPy
media_salario = np.mean(df["salario"])
std_salario = np.std(df["salario"])

z_scores = np.abs((df["salario"] - media_salario) / std_salario)

# Filtramos valores con un Z-score mayor a 3
outliers_z = z_scores > 3
print(f"Número de outliers detectados por Z-score: {outliers_z.sum()}")
🔥 Importante: Detectar un outlier no significa que debas eliminarlo automáticamente. Siempre investiga la naturaleza del dato: ¡un valor extremadamente alto en salarios podría ser un CEO real o simplemente un error de digitación!

Optimización y Limpieza de Duplicados en Bloque 🚀

Para finalizar nuestro pipeline de limpieza, debemos deshacernos de las filas duplicadas que introdujimos al inicio del tutorial. Pandas nos permite controlar exactamente qué filas conservar basándonos en subconjuntos de columnas.

# Eliminamos duplicados exactos
df.drop_duplicates(inplace=True)

# Si quisiéramos eliminar duplicados basándonos solo en el ID del cliente:
df.drop_duplicates(subset=["id_cliente"], keep="first", inplace=True)

print(f"Dimensiones finales del DataFrame limpio: {df.shape}")

Resumen del Proceso de Limpieza

A continuación, se presenta una tabla comparativa de las herramientas utilizadas y su propósito principal en el flujo de trabajo:

Herramienta / MétodoPropósito PrincipalCuándo Utilizarlo
---------
df.dropna() / fillna()Gestión de valores nulosDatos faltantes por errores de captura o sensores
str.strip() / str.upper()Estandarización de textoLimpieza de columnas categóricas con entradas manuales
---------
Rango IQRDetección de outliers no paramétricosVariables con distribuciones sesgadas (ej. ingresos)
Z-Score (NumPy)Detección de outliers paramétricosVariables con distribución normal o gaussiana
---------
drop_duplicates()Eliminación de registros repetidosAuditoría posterior a cruces o uniones de tablas

Nivel Intermedio-Avanzado Pandas & NumPy

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!