Resumen
El episodio 161 de enCoders presenta Polars (librería de DataFrames escrita en Rust, con wrapper para Python) y el formato Parquet como alternativa eficiente a Pandas y CSV cuando se trabaja con volúmenes grandes de datos. El anfitrión cuenta su experiencia con datasets de unos 150 GB y explica tres ejes de eficiencia: velocidad de lectura, menor uso de RAM y aprovechamiento de todos los núcleos de CPU. Se demuestra en vivo que Parquet pesa unas tres veces menos que CSV y que Polars lee mucho más rápido que Pandas. Se explican las expresiones de Polars y el modo lazy frente al eager, con `explain`, `collect` y `engine="streaming"`. Un benchmark con joins y agregaciones sobre 20 millones de filas da unos 0,33 s en Polars frente a unos 6-7 s en Pandas. Las conclusiones: Parquet por encima de CSV, Polars por defecto cuando el volumen lo exige, y el streaming ayuda pero no resuelve todos los casos (sort y joins pueden bloquearlo).
Capítulos
- 00:00IntroPresentan el tema (Polars y Parquet) y discuten un comentario del chat sobre si Polars es una librería de R o un wrapper. Aclaran que está escrita en Rust y que la versión de Python es un wrapper.
- 01:42Motivación para Usar PolarsEl anfitrión cuenta su experiencia de 5-6 años en data science con datasets de hasta 150 GB, donde Pandas no logra ni cargar los datos. Pone el ejemplo de una cadena de retail con 10 millones de clientes y 300 millones de transacciones; el peso en disco describe mejor el tamaño que las filas. Se cierra con "Pandas se convirtió en el nuevo Excel".
- 05:19Introducción a ParquetPlantea tres objetivos: velocidad de lectura, menor uso de RAM y uso de todos los núcleos. Con instancias de AWS ilustra costos (de unos 4 USD/hora para 512 GB de RAM a unos 600 USD/mes) y se discute si desarrollar con una muestra o con los primeros 10 registros. Explica que Parquet es columnar y se guarda en row groups, que permite leer solo las columnas necesarias y que admite particiones (por ejemplo por día).
- 26:57Demo: Parquet versus CSVSe genera un DataFrame aleatorio de 20 millones de filas y 10 columnas, guardado en CSV y Parquet. Parquet pesa unas tres veces menos, lo que ahorra costos en S3, y conserva los tipos de columna en los metadatos. Se comenta que Pickle no es recomendable para datos y que Parquet permite usar servicios como Athena con SQL.
- 35:16Comparación de Velocidad: Pandas vs Polars, CSV vs ParquetBenchmark de lectura de dos columnas: Polars lee el CSV en unos 0,6 s y Pandas en unos 9,4 s. Con Parquet, Pandas tarda unos 1,2 s y Polars una fracción mucho menor. Se menciona el benchmark público PDS-H, donde Polars gana en todas las curvas y Pandas queda último.
- 40:21Expresiones en Polars: Conceptos y EjemplosUna expresión es la representación de una transformación de los datos, modular y componible (`pl.col("a") * 2`, `.alias`). El estilo es declarativo, distinto al de Pandas. Se aclara que "dynamic integer" es un entero cuyo tamaño se decide en tiempo de ejecución.
- 44:07Comparación de Sintaxis: Pandas vs PolarsEjemplo del IMC con categorización por condiciones, hecho con indexación booleana en Pandas y con `with_columns` y `when/then/otherwise` en Polars. Al anfitrión le resulta más ergonómico Polars aunque no supera a R/dplyr según los comentarios. Las operaciones típicas son group by, filter, select, transformaciones y sort.
- 51:15MemesSe comentan memes enviados por la comunidad en Discord (spinners de "thinking", planificación de proyectos, Claude y el feedback, data engineer/scientist/contable y dbt). Incluye uno sobre no usar CSV en Pandas y otro con los beneficios de Polars.
- 55:26Demostración en Vivo: Modo Lazy vs Modo EagerExplica las tres capas del modo lazy: la instrucción del usuario, el plan optimizado y la ejecución. Con `read_parquet` se obtiene modo eager y con `scan_parquet` modo lazy. Se muestra el truco de convertir un DataFrame en lazy y que sin `collect` no se ejecuta nada. Se aclara que lazy no es invento de Polars (Spark, dplyr).
- 01:07:45Ejecutando el Código y Observaciones InicialesSe mide la RAM en el Administrador de tareas: en modo eager el uso salta a unos 2 GB al leer el parquet, y la operación tarda unos 0,16 s. En modo lazy no hay salto de RAM hasta ejecutar `collect`.
- 01:08:25Entendiendo la Función Explain`explain` muestra el plan: el optimizador detecta que solo se necesitan las columnas user, F1 y F2 (projection pushdown) y hace el casteo de tipos. El resto de columnas no se lee.
- 01:09:28Ejecutando la Operación CollectAl ejecutar `collect` la consulta tarda unos 0,08 s frente a unos 0,16 s en eager, con el mismo número de filas. Un comentario relaciona la "π" del plan con la proyección del álgebra relacional.
- 01:10:58Procesamiento de Datos en StreamingEl `collect` con streaming procesa por lotes: en el ejemplo de group by por región baja el pico de RAM en un orden de magnitud (de unos 1,5 GB) con tiempo similar. Gracias a esto procesó el archivo de 150 GB. No es perfecto: en su experiencia a veces la RAM igualmente se agotó.
- 01:17:35Comparando Polars y PandasUna consulta con varios joins, filtro y agregaciones sobre 20 millones de filas tarda unos 0,33 s en Polars y unos 6-7 s en Pandas (unas 20 veces más). Un comentario de Yair señala que sort, joins y otras operaciones globales bloquean el streaming. El anfitrión confirma que le ha pasado y que Polars cae a modo normal sin error.
- 01:26:10Consejos y Técnicas PrácticasPara depurar usa `limit` aplicado al scan inicial, no al final, para que el plan lo respete. PySpark tiene sintaxis muy parecida, aunque exige configurar el motor. Se mencionan soporte de GPU (`engine="gpu"`), SQL, plugins (geoespaciales), gráficos nativos y compatibilidad con otras librerías, además de cómo enviar código a la terminal en VS Code. Se advierte que conviene cuidar el esquema al guardar Parquet.
- 01:40:26CierreCierran con el mensaje de que Polars debería conocerse más y que cuesta ver ventajas de Pandas más allá de la adopción. Cuando los tiempos pasan de segundos a minutos u horas, el cambio puede hacer viable un proyecto. Anuncian el raid y el horario de los martes de 19 a 21 h (hora de Santiago).