Skip to content

Pandas Data Cleaning: Flujo práctico

Updated on

Los datos sucios bloquean el análisis temprano. Parches rápidos con fillna o reemplazos de texto esconden problemas reales: tipos erróneos, duplicados silenciosos o outliers que sesgan métricas.

Marco PAS:

  • Problema: Tipos mixtos, nulos y duplicados rompen joins y sesgan estadísticas.
  • Agitar: Arreglos puntuales ocultan fallas hasta tarde en el proyecto y generan retrabajo.
  • Solución: Un checklist repetible: estandarizar tipos, tratar nulos de forma intencional, manejar outliers, deduplicar y validar antes de exportar.

Workflow de un vistazo

PasoQué hacerEjemplo
1. PerfilarVer columnas, nulos, únicosdf.info(), df.describe(include="all")
2. Normalizar columnasLimpiar nombres/textodf.columns = df.columns.str.strip().str.lower()
3. Corregir tiposto_datetime, to_numeric, astype("category")df["date"] = pd.to_datetime(df["date"], errors="coerce")
4. Tratar faltantesBorrar o rellenar con reglasdf["age"] = df["age"].fillna(df["age"].median())
5. Tratar outliersCap/flagdf["rev_cap"] = df["revenue"].clip(upper=df["revenue"].quantile(0.99))
6. DeduplicarEliminar duplicados exactos/parcialesdf.drop_duplicates(subset=["id", "date"], keep="last")
7. ValidarAfirmar rangos/categoríasassert df["score"].between(0,100).all()

1) Perfila rápido

summary = {
    "rows": len(df),
    "columns": df.shape[1],
    "nulls": df.isna().sum(),
    "unique_counts": df.nunique(),
}
  • Detecta tipos mezclados pronto (df.info()).
  • Observa sesgos con df.describe(percentiles=[0.01,0.99]).

2) Normaliza columnas y texto

df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
df["country"] = df["country"].str.strip().str.title()
  • Nombres estándar simplifican joins y código.
  • Usa .str.normalize("NFKC") si hay caracteres raros.

3) Corrige tipos

df["date"] = pd.to_datetime(df["date"], errors="coerce", utc=True)
df["amount"] = pd.to_numeric(df["amount"], errors="coerce")
df["segment"] = df["segment"].astype("category")
  • errors="coerce" expone valores malos como NaT/NaN.
  • convert_dtypes() da tipos con nulos y ahorro de memoria en lote.

4) Maneja valores faltantes

df["age"] = df["age"].fillna(df["age"].median())
df["city"] = df["city"].fillna("Unknown")
df = df.dropna(subset=["id"])  # clave obligatoria
  • Decide por columna: numérica → mediana/media; categórica → modo/placeholder.
  • Conserva señal con flags: df["age_imputed"] = df["age"].isna().

5) Maneja outliers

upper = df["revenue"].quantile(0.99)
lower = df["revenue"].quantile(0.01)
df["revenue_capped"] = df["revenue"].clip(lower=lower, upper=upper)
  • Para ratios, usa z-score: abs(z) < 3.
  • En finanzas, mejor capear que borrar para no alterar el conteo.

6) Deduplica con cuidado

df = df.drop_duplicates(subset=["id", "date"], keep="last")
  • Confirma la clave única: assert df.duplicated(["id"]).sum() == 0.
  • Para coincidencias borrosas, normaliza (p. ej. correos en minúsculas) antes.

7) Valida antes de exportar

assert df["score"].between(0, 100).all()
valid_segments = {"basic", "pro", "enterprise"}
assert df["segment"].isin(valid_segments).all()
  • Usa pd.testing.assert_frame_equal en tests para comparar salidas.
  • Incluye chequeos ligeros de filas y nulos en pipelines para detectar regresiones.

Mini pipeline end-to-end

def clean(df):
    df = df.copy()
    df.columns = df.columns.str.strip().str.lower()
    df["date"] = pd.to_datetime(df["date"], errors="coerce")
    df["amount"] = pd.to_numeric(df["amount"], errors="coerce")
    df["amount"] = df["amount"].fillna(df["amount"].median())
    df["segment"] = df["segment"].fillna("unknown").str.lower()
    df = df.dropna(subset=["id"])
    df = df.drop_duplicates(subset=["id", "date"], keep="last")
    assert df["amount"].ge(0).all()
    return df
  • Copia primero para no mutar el input.
  • Con df.pipe(clean) el pipeline se lee fácil.

Guías relacionadas


Claves finales

  • Estandariza nombres, fuerza tipos, trata nulos con intención.
  • Capea o marca outliers en vez de borrar silenciosamente.
  • Valida claves y rangos antes de exportar a BI o analítica.