Pandas en contexto
De donde viene pandas
Wes McKinney creo pandas en 2008 mientras trabajaba en AQR Capital Management, un hedge fund cuantitativo. El problema era concreto: Python no tenia una herramienta decente para manipular datos tabulares con series de tiempo. R tenia su data.frame, pero Python solo ofrecia NumPy (arrays sin etiquetas), listas de diccionarios, o csv.reader manual.
El nombre viene de panel data — un termino de econometria para datos longitudinales (multiples entidades observadas a lo largo del tiempo). No tiene nada que ver con el animal.
McKinney lo hizo open source en 2009. Hoy es la libreria de datos tabulares mas usada en Python, con millones de descargas mensuales.
Por que importa saber esto
Pandas fue disenado por un financiero que necesitaba mover datos rapido, no por un computer scientist optimizando rendimiento. Esto explica muchas decisiones de diseno:
- API enorme (200+ metodos en DataFrame) porque queria que todo fuera “una linea”
- Indices con etiquetas y alineacion automatica — util para series de tiempo, confuso para todo lo demas
NaNcomo float de IEEE 754 — heredado de NumPy, con consecuencias que veremos- Flexibilidad sobre rigidez — pandas rara vez te dice “no”, pero a veces deberia
Que problema resuelve (y cual no)
Pandas es una herramienta para datos tabulares que caben en RAM. Punto. Si tu problema se describe como “tengo una tabla con filas y columnas, y quiero transformarla”, pandas probablemente es la respuesta correcta.
Pero no siempre. El error mas comun es usar pandas para todo:
| Situacion | Herramienta correcta | Por que no pandas |
|---|---|---|
| Tabla que cabe en RAM | pandas | — |
| Tabla en RAM, necesitas velocidad | polars | Rust, lazy eval, sin GIL, 2-10x mas rapido |
| No cabe en RAM | dask, PySpark, SQL | pandas carga todo en memoria |
| Solo filtrar y agregar | SQL directo | Mas claro, mas rapido, no necesitas Python |
| Arrays numericos sin etiquetas | NumPy directo | Menos overhead que un DataFrame |
| Datos jerarquicos/documentos | diccionarios, JSON | No fuerces un DataFrame donde no aplica |
| Iterar fila por fila | listas/dicts o repensar | Si haces iterrows() probablemente no necesitas pandas |
La regla practica
Si cabe en RAM y es tabular → pandas. Si cabe en RAM y necesitas velocidad → evalua polars. Si no cabe en RAM → necesitas otra cosa.
“Cabe en RAM” no significa que tu archivo sea menor que tu RAM. Pandas usa de 2x a 10x el tamano del archivo en memoria (por tipos, indices, overhead interno). Un CSV de 2 GB puede necesitar 8-10 GB de RAM.
La relacion con NumPy (y Arrow)
Pandas esta construido sobre NumPy. Cada Series es un wrapper de un np.ndarray. Esto tiene consecuencias directas:
- Vectorizacion: las operaciones que son rapidas en NumPy son rapidas en pandas. Las que no, no.
- Missings:
np.nanes unfloatde IEEE 754. Por eso una columna de enteros con un missing se convierte en float. No es un bug de pandas — es una limitacion heredada de NumPy. - Strings: NumPy no tiene un tipo string nativo. Pandas los mete en
object(array de punteros a objetos Python) — lento y pesado.
pandas 2.x esta migrando a Apache Arrow (via PyArrow) como backend alternativo. Arrow maneja strings nativamente, tiene nullable types integrados, y es mas eficiente en memoria. Todavia es opcional, pero es el futuro.
# Backend clasico (NumPy)
df = pd.read_csv("datos.csv")
# Backend Arrow (pandas 2.x)
df = pd.read_csv("datos.csv", dtype_backend="pyarrow")
El ecosistema: donde encaja pandas
Pandas no vive solo. Es el pegamento del ecosistema de datos en Python:
┌─────────────┐
│ Fuentes │
│ CSV, SQL, │
│ Parquet,API │
└──────┬──────┘
│ pd.read_*
▼
┌────────────────────────┐
│ pandas │
│ Limpiar, transformar, │
│ explorar, agregar │
└───┬────────┬───────┬───┘
│ │ │
▼ ▼ ▼
matplotlib scikit to_parquet
seaborn learn to_sql
plotly XGBoost to_csv
- Entrada:
read_csv,read_parquet,read_sql,read_json,read_excel - Procesamiento: pandas para transformar, NumPy para calculo vectorizado pesado
- Salida: Parquet (entre sistemas), CSV (para humanos), SQL (para produccion)
- Visualizacion: matplotlib, seaborn, plotly — todos entienden DataFrames nativamente
- ML: scikit-learn, XGBoost, LightGBM esperan DataFrames o arrays como input
Cuando escalar mas alla de pandas
Si tu pipeline en pandas tarda demasiado o se queda sin memoria, tienes opciones:
| Libreria | Modelo | Cuando usarla |
|---|---|---|
| polars | Single machine, Rust, lazy | DataFrames grandes, necesitas velocidad, API similar |
| dask | Paralelo, distribuido | DataFrames que no caben en RAM, cluster |
| PySpark | Distribuido, JVM | Datos masivos, infraestructura enterprise |
| DuckDB | SQL analitico, in-process | Queries analiticas sobre archivos locales |
No te cambies a otra herramienta “por si acaso”. Pandas resuelve el 90% de los casos reales en ciencia de datos. Cambia cuando pandas te de un problema concreto, no antes.
Versiones que importan
pandas tiene dos eras:
| pandas 1.x | pandas 2.x | |
|---|---|---|
| Backend | NumPy | NumPy + Arrow (opcional) |
| Copy-on-Write | Off | On por default |
| Nullable dtypes | Experimentales | Estables |
| Strings | object |
StringDtype / Arrow string |
| Fecha release | 2020 | 2023 |
import pandas as pd
print(pd.__version__) # Saber tu version es el paso 0
Copy-on-Write (CoW)
El cambio más importante de pandas 2.x es cómo maneja “subsets” (subconjuntos) de datos.
Cuando haces algo como df[df["x"] > 0] o df[["a", "b"]], obtienes un subset: otro objeto “basado en” df.
- Vista (view): el subset comparte los mismos datos en memoria que el DataFrame original. Si escribes sobre la vista, puedes terminar modificando el original.
- Copia (copy): el subset trae sus propios datos (memoria separada). Si escribes, el original no cambia.
En pandas 1.x, a veces obtenías una vista y a veces una copia (según el caso y optimizaciones internas). Por eso era difícil razonar si esta línea iba a afectar a df o no.
El SettingWithCopyWarning es justamente la alerta de “no estoy seguro si estás modificando una copia o una vista; tu asignación puede no hacer lo que crees”.
Con Copy-on-Write, el comportamiento se vuelve más predecible:
- Lecturas: los objetos pueden compartir memoria (eficiente).
- Escrituras: si intentas modificar un subset, pandas primero separa los datos necesarios (hace la copia en ese momento) y luego aplica el cambio.
Eso es lo que significa copia lógica: se comporta como si fuera una copia desde el punto de vista del usuario, aunque la copia física solo ocurra cuando escribes. Resultado: menos ambigüedad, menos warnings y menos bugs silenciosos.
Filosofia y consejo practico
Pandas tiene una API enorme. DataFrame tiene mas de 200 metodos. No necesitas conocerlos todos — dominar 20-30 cubre el 90% de los casos reales.
Los LLMs conocen toda la API pero no siempre eligen el metodo correcto para tu contexto. Saber cuando no usar pandas y como estructurar tu codigo es mas valioso que memorizar metodos. Eso es lo que cubre el siguiente capitulo.
Piensa en un proyecto de datos que hayas hecho (o un ejercicio del curso anterior). ¿Hubo algun momento donde pandas no era la herramienta correcta? ¿Usaste iterrows() o un loop sobre el DataFrame? ¿Que alternativa habrias usado sabiendo lo que sabes ahora?