Data Wrangling: Guía Completa para Limpiar y Transformar Datos con Python
Updated on
Todo proyecto de datos comienza con la misma verdad incómoda: los datos sin procesar son desordenados. Las columnas tienen formatos inconsistentes. Las fechas llegan como strings. Los registros de clientes contienen duplicados. No puedes construir modelos, dashboards o informes confiables sobre datos en los que no confías.
Data wrangling es el proceso de convertir esos datos crudos y poco confiables en algo limpio, estructurado y listo para el análisis. Consume hasta el 80% del tiempo de un profesional de datos según múltiples encuestas de la industria. Esta guía recorre todo el pipeline de data wrangling usando Python y Pandas, con código práctico para cada paso.
¿Qué es Data Wrangling?
Data wrangling (también llamado data munging) es el proceso de descubrir, estructurar, limpiar, enriquecer y validar datos sin procesar para que puedan usarse para análisis o machine learning.
Data Wrangling vs Data Cleaning vs ETL
| Término | Alcance | Enfoque | Herramientas Típicas |
|---|---|---|---|
| Data Wrangling | Amplio -- cubre todo el proceso | Exploración, reshape, limpieza, enriquecimiento | Pandas, Polars, scripts Python |
| Data Cleaning | Estrecho -- un subconjunto del wrangling | Corregir errores, manejar valores faltantes | Pandas, OpenRefine, SQL |
| ETL | Nivel de sistema -- pipelines automatizados | Mover datos entre sistemas a escala | Airflow, dbt, Spark |
El Pipeline de Data Wrangling
1. Descubrir -- Cargar los datos y entender su forma, tipos y problemas.
2. Estructurar -- Reshape columnas y filas para que los datos coincidan con el esquema necesario.
3. Limpiar -- Manejar valores faltantes, corregir tipos de datos, eliminar duplicados.
4. Enriquecer -- Agregar columnas derivadas, unir con datasets externos.
5. Validar -- Confirmar que la salida cumple con las expectativas.
Etapa 1: Descubrir tus Datos
import pandas as pd
df = pd.read_csv("sales_data.csv")
print(f"Filas: {df.shape[0]}, Columnas: {df.shape[1]}")
df.info()
df.describe(include="all")
df.isnull().sum().sort_values(ascending=False)
print(f"Filas duplicadas: {df.duplicated().sum()}")
for col in df.select_dtypes(include="object").columns:
print(f"{col}: {df[col].nunique()} valores únicos")
print(df[col].value_counts().head(5))
print()Para un enfoque visual, PyGWalker (opens in a new tab) convierte cualquier DataFrame de Pandas en una interfaz interactiva tipo Tableau:
import pygwalker as pyg walker = pyg.walk(df)
Etapa 2: Estructurar y Reshape
# Estandarizar nombres de columnas
df.columns = (
df.columns.str.strip().str.lower().str.replace(" ", "_").str.replace(r"[^\w]", "", regex=True)
)
# Pivot: formato largo a ancho
sales_wide = df.pivot_table(index="product", columns="month", values="revenue", aggfunc="sum")
# Melt: formato ancho a largo
sales_long = sales_wide.reset_index().melt(id_vars="product", var_name="month", value_name="revenue")Etapa 3: Limpiar los Datos
Manejo de Valores Faltantes
df_dropped = df.dropna(subset=["revenue", "customer_id"])
df["category"] = df["category"].fillna("Desconocido")
df["revenue"] = df["revenue"].fillna(df["revenue"].median())
df["price"] = df["price"].ffill()
df["temperature"] = df["temperature"].interpolate(method="linear")| Situación | Enfoque Recomendado |
|---|---|
| Menos del 5% faltante, aleatorio | Eliminar filas |
| Columna categórica | Llenar con "Desconocido" o moda |
| Columna numérica, distribución normal | Llenar con media |
| Columna numérica, distribución sesgada | Llenar con mediana |
| Datos de series temporales | Forward fill o interpolación |
| Columna con > 50% faltante | Considerar eliminar la columna |
Conversiones de Tipos de Datos
df["order_date"] = pd.to_datetime(df["order_date"], format="%Y-%m-%d")
df["revenue"] = pd.to_numeric(df["revenue"], errors="coerce")
df["status"] = df["status"].astype("category")
df["is_active"] = df["is_active"].map({"yes": True, "no": False, "Y": True, "N": False})Limpieza de Strings
df["name"] = df["name"].str.strip()
df["city"] = df["city"].str.lower()
df["phone"] = df["phone"].str.replace(r"[^\d]", "", regex=True)
df["zip_code"] = df["address"].str.extract(r"(\d{5})")Manejo de Duplicados
print(f"Duplicados totales: {df.duplicated().sum()}")
df = df.drop_duplicates(subset=["customer_id", "order_date"], keep="first")Etapa 4: Enriquecer -- Fusionar y Unir Datasets
merged = pd.merge(orders, customers, on="customer_id", how="left")
all_months = pd.concat([jan_df, feb_df, mar_df], ignore_index=True)
# Columnas calculadas
df["profit"] = df["revenue"] - df["cost"]
df["profit_margin"] = (df["profit"] / df["revenue"] * 100).round(2)
df["revenue_tier"] = pd.cut(df["revenue"], bins=[0, 100, 500, 1000, float("inf")], labels=["Bajo", "Medio", "Alto", "Premium"])| Tipo de Join | Mantiene | Usar Cuando |
|---|---|---|
inner | Solo filas coincidentes | Necesitas registros completos |
left | Todas las filas de la izquierda | La tabla izquierda es tu dataset principal |
right | Todas las filas de la derecha | La tabla derecha es tu dataset principal |
outer | Todas las filas de ambas tablas | Necesitas la unión completa |
Etapa 5: Validar
def validate_dataframe(df):
checks = {}
required = ["customer_id", "order_date", "revenue"]
for col in required:
null_count = df[col].isnull().sum()
checks[f"no_nulls_{col}"] = null_count == 0
neg_revenue = (df["revenue"] < 0).sum()
checks["positive_revenue"] = neg_revenue == 0
passed = sum(checks.values())
total = len(checks)
print(f"\nValidación: {passed}/{total} verificaciones pasaron")
return checks
validate_dataframe(df)Detección de Valores Atípicos
import numpy as np
Q1 = df["revenue"].quantile(0.25)
Q3 = df["revenue"].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
# Opción A: Eliminar
df_clean = df[(df["revenue"] >= lower) & (df["revenue"] <= upper)]
# Opción B: Recortar (winsorización)
df["revenue_capped"] = df["revenue"].clip(lower=lower, upper=upper)Pandas vs Polars vs SQL
| Criterio | Pandas | Polars | SQL |
|---|---|---|---|
| Velocidad | Lento (single-thread) | Rápido (multi-thread, Rust) | Depende del motor |
| Mejor para | Análisis exploratorio | Datasets grandes | Datos en bases de datos |
Data Wrangling Asistido por IA
RunCell (opens in a new tab) trae un agente IA directamente a tu notebook Jupyter. Describe lo que necesitas en lenguaje natural y RunCell genera el código Pandas.
FAQ
¿Qué es data wrangling en términos simples?
Data wrangling es el proceso de tomar datos crudos y desordenados y convertirlos en un formato limpio y estructurado adecuado para el análisis.
¿Cuál es la diferencia entre data wrangling y data cleaning?
Data cleaning es un paso dentro de data wrangling. Cleaning se enfoca en corregir errores. Wrangling es más amplio e incluye exploración, reestructuración, enriquecimiento y validación.
¿Qué herramientas se usan para data wrangling?
Python con Pandas es la más común. Otras opciones incluyen Polars, SQL y R con dplyr. PyGWalker proporciona exploración visual interactiva.
¿Cuánto tiempo dedican los científicos de datos al data wrangling?
Las encuestas reportan que los profesionales de datos dedican 60-80% de su tiempo a data wrangling.
¿Cuáles son los pasos del data wrangling?
Los cinco pasos principales son: Descubrir, Estructurar, Limpiar, Enriquecer y Validar.
Conclusión
Data wrangling es la base que hace posible todo análisis posterior. Los puntos clave: siempre explorar antes de limpiar, usar el pipeline de cinco etapas, elegir la estrategia correcta para valores faltantes, validar la salida y documentar las decisiones.
Construye tu lógica de wrangling en funciones reutilizables. Los datos cambiarán. Las fuentes cambiarán. Tu pipeline debería manejar ambos con elegancia.