(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo limpiar y normalizar datos de texto en un ETL con pandas

João Barros 10 de July de 2026 4 min de lectura

Los datos de texto que llegan de formularios, exportaciones o APIs casi siempre vienen desordenados: espacios de más, mayúsculas inconsistentes, acentos y la misma categoría escrita de varias formas. Aprender a limpiar y normalizar datos de texto en un ETL con pandas asegura que estos valores queden consistentes antes de cargarlos en el destino, y es uno de los pasos que más evita errores y duplicados posteriores. Usaremos un ejemplo sencillo con nombres de ciudades y estados, pero el mismo enfoque sirve para cualquier columna de texto.

Requisitos previos

  • Python 3.10 o superior instalado.
  • La biblioteca pandas instalada (pip install pandas).
  • Conocimientos básicos de DataFrame y de cómo ejecutar un script de Python.

Paso 1: Preparar datos de ejemplo

Para ver el efecto de cada transformación, empieza por crear un DataFrame pequeño que imita datos reales "sucios": la misma ciudad escrita de formas diferentes y un estado con mayúsculas inconsistentes. Datos así aparecen cuando varias personas rellenan el mismo campo a mano o cuando se combinan archivos de orígenes distintos.

import pandas as pd

df = pd.DataFrame({
    "cidade": ["  Lisboa ", "PORTO", "porto ", "Évora", " lisboa"],
    "estado": ["Ativo", "ativo ", "INATIVO", " Ativo", "inativo"],
})
print(df)

Fíjate en que "Lisboa", " lisboa" y "PORTO" representan solo dos ciudades, pero el ordenador las ve como valores diferentes. Eso es lo que vamos a corregir.

Paso 2: Eliminar espacios de más

El primer problema son los espacios al principio, al final y repetidos dentro del texto. El método str.strip() recorta los extremos y str.replace() con una expresión regular junta varios espacios en uno. Lo aplicamos a todas las columnas de texto a la vez.

for col in ["cidade", "estado"]:
    df[col] = df[col].str.strip()
    df[col] = df[col].str.replace(r"\s+", " ", regex=True)
Consejo: desde pandas 2.0, el parámetro regex de str.replace() es False por defecto. Indica siempre regex=True cuando uses un patrón.

Paso 3: Unificar mayúsculas y minúsculas

"PORTO", "porto" y "Porto" deberían ser el mismo valor. Aplicamos str.title() a los nombres de ciudad, para que empiecen con mayúscula, y str.lower() al estado, que vamos a estandarizar a continuación. Usamos str.title() en lugar de str.upper() porque queremos nombres legibles, no todo en mayúsculas.

df["cidade"] = df["cidade"].str.title()
df["estado"] = df["estado"].str.lower()

Paso 4: Eliminar acentos

Para crear claves consistentes — por ejemplo, para unir tablas por nombre de ciudad — conviene eliminar los acentos. La normalización NFKD separa la letra del acento; al codificar en ASCII ignorando lo que no cabe, los acentos desaparecen y "Évora" queda como "Evora".

df["cidade"] = (
    df["cidade"]
    .str.normalize("NFKD")
    .str.encode("ascii", "ignore")
    .str.decode("utf-8")
)

Paso 5: Estandarizar categorías con un diccionario

Por último, asignamos cada variación a una etiqueta oficial con un diccionario y el método map(). Un valor que no esté en el diccionario queda como NaN — lo que es útil, porque delata categorías inesperadas que aún no has tratado. Si prefieres mantener los valores desconocidos en lugar de convertirlos en NaN, usa replace() en vez de map().

mapa_estado = {"ativo": "Ativo", "inativo": "Inativo"}
df["estado"] = df["estado"].map(mapa_estado)

Verificar el resultado

Confirma el resultado imprimiendo los valores únicos de cada columna y el recuento de valores ausentes. Si la limpieza salió bien, cada ciudad y cada estado aparecen escritos de una sola forma.

print(df["cidade"].unique())
print(df["estado"].unique())
print(df.isna().sum())

Deberías obtener ['Lisboa' 'Porto' 'Evora'] en las ciudades y ['Ativo' 'Inativo'] en los estados, sin valores ausentes. Si aparece algún NaN, hay una categoría que quedó sin asignar en el Paso 5.

Conclusión

Con unos pocos métodos de pandas transformaste texto inconsistente en datos limpios y predecibles, listos para la fase de carga de tu ETL. El siguiente paso natural es reunir estas transformaciones en una función reutilizable y aplicarla a cada archivo que procesas, garantizando el mismo tratamiento en todo el pipeline. ¿Qué otra columna de tu conjunto de datos ganaría con ser normalizada de esta forma?