Pandas es muy potente, pero un uso descuidado puede volverlo lento o hambriento de memoria. Este tema resume buenas prácticas para optimizar recursos y aprovechar la vectorización.
Trabajaremos con un DataFrame grande simulado usando NumPy y revisaremos estrategias para cargas voluminosas.
Por defecto, Pandas asigna tipos amplios (int64
, float64
, object
). Reducirlos a variantes más pequeñas puede ahorrar decenas de megabytes.
Ejemplo inicial
import pandas as pd
import numpy as np
# DataFrame grande simulado
df = pd.DataFrame({
"ID": np.arange(1, 1_000_001),
"Edad": np.random.randint(18, 90, size=1_000_000),
"Salario": np.random.randint(30_000, 120_000, size=1_000_000),
"Ciudad": np.random.choice(["Córdoba", "Buenos Aires", "Rosario"], size=1_000_000)
})
print(df.info(memory_usage="deep"))
object
guarda cadenas como punteros independientes; reemplazarlo por categorías o cadenas más cortas reduce el consumo.Optimizar tipos numéricos
df["ID"] = df["ID"].astype("int32")
df["Edad"] = df["Edad"].astype("int8")
df["Salario"] = df["Salario"].astype("int32")
print(df.info(memory_usage="deep"))
Optimizar texto con category
df["Ciudad"] = df["Ciudad"].astype("category")
print(df.info(memory_usage="deep"))
Los bucles for
en Python son costosos. Pandas y NumPy ofrecen operaciones vectorizadas que operan sobre columnas completas en C.
Ejemplo con bucle (lento)
# Calcular impuesto (20 %) con for
df["Impuesto_for"] = [salario * 0.20 for salario in df["Salario"]]
Versión vectorizada (rápida)
df["Impuesto_vec"] = df["Salario"] * 0.20
Evitar apply
cuando no es necesario
df["Salario_doble_apply"] = df["Salario"].apply(lambda x: x * 2)
df["Salario_doble_vec"] = df["Salario"] * 2
apply
/map
para lógicas personalizadas difíciles de expresar con operadores nativos.Cuando los datos exceden la memoria disponible, combiná lectura incremental, formatos eficientes y filtros previos.
Leer por partes con chunksize
for chunk in pd.read_csv("datos_grandes.csv", chunksize=100_000):
print(chunk["Salario"].mean())
Definir tipos al cargar
df = pd.read_csv("datos.csv", dtype={"Edad": "int8", "Ciudad": "category"})
Formatear en Parquet o Feather (formatos columnar optimizados para lectura/escritura rápida)
df.to_parquet("datos.parquet", index=False)
df = pd.read_parquet("datos.parquet")
Filtrar antes de cargar
df = pd.read_csv("datos.csv", usecols=["ID", "Edad", "Salario"])
dtypes
y usando category
en columnas repetitivas.apply
innecesarios.chunksize
, dtype
al leer y formatos columnar como Parquet.