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

Cómo procesar archivos CSV grandes en ETL con pandas

João Barros 07 de July de 2026 5 min de lectura

Trabajar con archivos CSV grandes es una tarea muy habitual en ETL, pero abrir un archivo de varios gigabytes de una sola vez puede agotar la memoria del ordenador y provocar el temido error MemoryError. Esto ocurre porque muchas rutinas de extracción cargan todo de una vez, sin pensar en el tamaño real de los datos. La solución es procesar el archivo por partes (chunks) con pandas, leyendo y transformando los datos poco a poco. Veamos, paso a paso, cómo procesar archivos CSV grandes en ETL de forma sencilla y segura.

Requisitos previos

  • Python 3.9 o superior instalado.
  • La biblioteca pandas: instálala con pip install pandas.
  • Un archivo CSV grande para probar (por ejemplo, vendas.csv con columnas como pais y valor).
  • Conocimientos básicos de Python (variables y bucles for).

Paso 1: Entender el problema

El método habitual, pd.read_csv("vendas.csv"), carga el archivo entero en la memoria RAM. Si el archivo tiene 5 GB, pandas necesita varios gigabytes libres, a menudo más que el tamaño del archivo, porque cada columna ocupa espacio adicional. En máquinas con poca memoria, el resultado es un MemoryError y el programa se detiene.

Cuando la memoria RAM se agota, el sistema operativo empieza a usar el disco como memoria virtual (swap), y el programa se vuelve extremadamente lento antes de, en muchos casos, fallar. La idea central es no tener nunca el archivo completo en memoria al mismo tiempo: leemos un bloque de filas, procesamos ese bloque, liberamos la memoria y pasamos al siguiente.

Paso 2: Leer el CSV por chunks

El parámetro chunksize de read_csv indica cuántas filas debe tener cada bloque. En lugar de un DataFrame, pandas devuelve un iterador que produce un DataFrame cada vez:

import pandas as pd

# cada bloco tem 100 000 linhas
for chunk in pd.read_csv("vendas.csv", chunksize=100_000):
    print(chunk.shape)

Cada chunk es un DataFrame normal de pandas. Puedes aplicarle todo lo que ya conoces: filtros, nuevas columnas, agrupaciones.

Consejo: empieza con bloques de 100 000 filas y ajusta según la memoria disponible. Los bloques más grandes son más rápidos pero usan más RAM; los más pequeños son más seguros en máquinas modestas.

Paso 3: Transformar y agregar cada bloque

En un pipeline ETL queremos transformar los datos y, muy a menudo, calcular un resumen. El siguiente ejemplo limpia cada bloque (mantiene solo valores positivos) y va sumando el total de ventas por país, acumulando el resultado en un diccionario:

import pandas as pd

total_por_pais = {}

for chunk in pd.read_csv("vendas.csv", chunksize=100_000):
    # transformar: manter apenas vendas com valor positivo
    chunk = chunk[chunk["valor"] > 0]
    # agregar: somar o valor por pais neste bloco
    soma = chunk.groupby("pais")["valor"].sum()
    for pais, valor in soma.items():
        total_por_pais[pais] = total_por_pais.get(pais, 0) + valor

resultado = pd.Series(total_por_pais).sort_values(ascending=False)
print(resultado)

Fíjate en que solo mantenemos en memoria el pequeño diccionario total_por_pais. Este patrón (resumir cada bloque y sumar los resúmenes) funciona para conteos, sumas y medias ponderadas, y es la base de cualquier agregación que no quepa en memoria de una sola vez.

Paso 4: Escribir el resultado sin agotar la memoria

Si el objetivo es guardar los datos ya procesados en otro archivo, escribe cada bloque a medida que lo procesas. El truco es escribir el encabezado solo en el primer bloque y usar el modo "a" (append) en los siguientes:

import pandas as pd

primeiro = True
for chunk in pd.read_csv("vendas.csv", chunksize=100_000):
    limpo = chunk[chunk["valor"] > 0]
    limpo.to_csv(
        "vendas_limpas.csv",
        mode="w" if primeiro else "a",
        header=primeiro,
        index=False,
    )
    primeiro = False

Así, el archivo de salida crece bloque a bloque y nunca necesita tener todo en memoria.

Paso 5: Reducir aún más la memoria (opcional)

Puedes ahorrar bastante memoria leyendo solo las columnas necesarias con usecols e indicando tipos más ligeros con dtype:

import pandas as pd

for chunk in pd.read_csv(
    "vendas.csv",
    usecols=["pais", "valor"],
    dtype={"valor": "float32"},
    chunksize=100_000,
):
    ...

Leer menos columnas y usar float32 en lugar de float64 reduce el espacio que ocupa cada bloque, permitiendo bloques más grandes o máquinas más modestas.

Verificar el resultado

Para confirmar que no perdiste datos, cuenta las filas del archivo de salida, también por chunks, para no volver a llenar la memoria:

import pandas as pd

total = sum(len(c) for c in pd.read_csv("vendas_limpas.csv", chunksize=100_000))
print("Linhas no ficheiro final:", total)

Compara este número con lo que esperabas después de la limpieza. Durante la ejecución, abre el Administrador de tareas (o el comando htop en Linux) y confirma que la memoria usada por Python se mantiene estable, en lugar de subir sin parar.

Conclusión

Con el parámetro chunksize puedes procesar archivos CSV mucho más grandes que la memoria disponible, manteniendo tu pipeline ETL estable y predecible. A partir de aquí, prueba a ajustar el tamaño del bloque a tu hardware y explora alternativas como polars o dask cuando necesites aún más velocidad. ¿Cuál es el archivo más grande que has tenido que procesar, y cuánto tardó?