Por que o pandas ainda domina — e quando ele falha
Com mais de 300 milhões de downloads mensais no PyPI [5], o pandas é a ferramenta de fato para manipulação de dados em Python. Sua popularidade não é sem razão: API intuitiva, ecossistema maduro (integração com scikit-learn, matplotlib, seaborn, sqlalchemy), documentação excelente e uma comunidade enorme.
O problema começa quando os datasets crescem. O pandas foi projetado numa era de CPUs single-core e memória RAM abundante, e carrega esse legado. Em operações típicas de análise de dados, o pandas:
- Usa apenas um core de CPU (sem paralelismo nativo)
- Copia dados em memória frequentemente (mutabilidade implícita)
- Executa operações eagerly (sem otimização de plano de execução)
- Usa tipos de dados com overhead alto (especialmente strings como
object)
Para datasets de até ~500MB, isso raramente importa. Para datasets de vários GBs — ou quando você está em um loop de ETL processando milhões de registros — o custo se torna proibitivo.
Polars: construído para o hardware moderno
O Polars foi criado por Ritchie Vink e lançado em 2021 [1]. Sua diferença fundamental é arquitetural: escrito em Rust (zero garbage collection, controle total de memória), usa Apache Arrow como formato de dados em memória (columnar, cache-friendly), e implementa paralelismo automático em todas as operações.
Mas o superpoder real do Polars é o lazy evaluation. Em vez de executar cada operação imediatamente, o Polars constrói um plano de execução lógico e o otimiza antes de rodar — similar ao que um otimizador de queries SQL faz:
import polars as pl
# Lazy: constrói um plano, não executa nada ainda
lf = (
pl.scan_csv("vendas_2024.csv") # Lê apenas o necessário
.filter(pl.col("valor") > 1000) # Predicado pushdown
.group_by("produto")
.agg([
pl.col("valor").sum().alias("receita_total"),
pl.col("quantidade").mean().alias("qtd_media"),
])
.sort("receita_total", descending=True)
)
# .collect() executa o plano otimizado
df = lf.collect()
print(df.head(10))
Com scan_csv em vez de read_csv, o Polars só lê as colunas que você realmente usa, e aplica os filtros durante a leitura — sem carregar o arquivo inteiro na memória.
Benchmarks: números reais de performance
O H2O.ai Database Benchmark [4] — o benchmark de referência para operações de DataFrame — testou Polars, pandas, DuckDB, Spark e outros em operações de groupby e join em datasets de 0.5GB e 5GB:
Comparação direta: sintaxe pandas vs Polars
A maior barreira de entrada no Polars é a sintaxe diferente. Veja a comparação lado a lado das operações mais comuns:
# ─── PANDAS ───────────────────────────────
import pandas as pd
df_pd = pd.read_csv("dados.csv")
# Filtro + agrupamento
resultado_pd = (
df_pd[df_pd["regiao"] == "Sul"]
.groupby("categoria")
.agg({"receita": "sum", "clientes": "nunique"})
.reset_index()
.rename(columns={"receita": "total", "clientes": "clientes_unicos"})
)
# ─── POLARS ───────────────────────────────
import polars as pl
df_pl = pl.read_csv("dados.csv")
# Filtro + agrupamento (mais expressivo e mais rápido)
resultado_pl = (
df_pl
.filter(pl.col("regiao") == "Sul")
.group_by("categoria")
.agg([
pl.col("receita").sum().alias("total"),
pl.col("clientes").n_unique().alias("clientes_unicos"),
])
)
DuckDB: SQL analytics dentro do Python
Se Polars é a evolução do pandas, o DuckDB é algo diferente: um banco de dados OLAP embutido que roda diretamente em Python [3]. Ele é projetado para analytics — leitura de grandes arquivos CSV/Parquet/JSON com SQL puro, sem servidor, sem configuração.
import duckdb
# DuckDB pode consultar DataFrames pandas/polars e arquivos diretamente
conn = duckdb.connect()
# Consultar arquivos Parquet diretamente com SQL
resultado = conn.execute("""
SELECT
categoria,
SUM(receita) AS total_receita,
COUNT(DISTINCT cliente_id) AS clientes_unicos,
AVG(ticket_medio) AS ticket_medio
FROM 'dados/**/*.parquet' -- Glob: lê múltiplos arquivos
WHERE ano = 2024
AND regiao IN ('Sul', 'Sudeste')
GROUP BY categoria
ORDER BY total_receita DESC
LIMIT 20
""").df() # .df() converte para pandas, .pl() para polars
Quando usar cada um
Use pandas quando:
- Dataset cabe confortavelmente em memória (< 500MB)
- Sua equipe já conhece pandas e o prazo não permite curva de aprendizado
- Você usa bibliotecas que só aceitam DataFrame pandas (ex: algumas versões de scikit-learn)
- Trabalho exploratório rápido em Jupyter notebook
Use Polars quando:
- Dataset > 1GB ou processamento em loop que se repete com frequência
- Pipeline de ETL onde performance e uso de memória são críticos
- Você quer aproveitar paralelismo multi-core sem configuração
- Processamento de arquivos Parquet em larga escala
E para o DuckDB: sempre que você precisar de SQL sobre arquivos locais (CSV, Parquet, JSON) ou quiser combinar dados de múltiplas fontes com JOINs complexos — sem precisar de um servidor de banco de dados.
A estratégia de migração pragmática
Você não precisa reescrever todo o código de uma vez. A estratégia mais inteligente é:
- Identifique os gargalos: Use
%timeitno Jupyter oucProfilepara encontrar as operações mais lentas. - Migre as etapas de transformação pesada: groupby, join, filter em datasets grandes são os candidatos principais.
- Mantenha pandas na interface: Converta de/para pandas apenas nos pontos de integração com outras bibliotecas.
- Adote Parquet como formato padrão: Substitua CSVs pesados por Parquet — tanto pandas quanto Polars leem muito mais rápido, e o DuckDB os consulta nativamente.
Referências
- Vink, R. Polars: Blazingly fast DataFrames in Rust, Python, Node.js, and more. Polars Documentation, 2024. Disponível em: pola.rs
- McKinney, W. Data Structures for Statistical Computing in Python. Proceedings of the 9th Python in Science Conference (SciPy 2010), pp. 56–61, 2010.
- DuckDB Foundation. DuckDB Documentation: An in-process SQL OLAP database management system. 2024. Disponível em: duckdb.org
- H2O.ai. Database-like ops benchmark. GitHub: h2oai/db-benchmark, 2023. Disponível em: github.com/h2oai/db-benchmark
- PyPI Stats. pandas download statistics. 2024. Disponível em: pypistats.org
Why pandas still dominates — and when it fails
With over 300 million monthly downloads on PyPI [5], pandas is the de facto tool for data manipulation in Python. But the problems start when datasets grow: pandas uses only one CPU core, copies data in memory frequently, executes operations eagerly without plan optimization, and uses high-overhead data types.
Polars: built for modern hardware
Polars was created by Ritchie Vink and released in 2021 [1]. Written in Rust, it uses Apache Arrow as the in-memory data format, and implements automatic parallelism in all operations. Its real superpower is lazy evaluation: instead of executing each operation immediately, Polars builds a logical execution plan and optimizes it before running — similar to what a SQL query optimizer does.
import polars as pl
# Lazy: builds a plan, executes nothing yet
lf = (
pl.scan_csv("sales_2024.csv") # Reads only what's needed
.filter(pl.col("amount") > 1000) # Predicate pushdown
.group_by("product")
.agg([
pl.col("amount").sum().alias("total_revenue"),
pl.col("quantity").mean().alias("avg_quantity"),
])
.sort("total_revenue", descending=True)
)
# .collect() runs the optimized plan
df = lf.collect()
print(df.head(10))
Benchmarks: real performance numbers
DuckDB: SQL analytics inside Python
DuckDB is an embedded OLAP database that runs directly in Python [3]. It's designed for analytics — reading large CSV/Parquet/JSON files with pure SQL, no server, no configuration.
import duckdb
conn = duckdb.connect()
# Query Parquet files directly with SQL
result = conn.execute("""
SELECT
category,
SUM(revenue) AS total_revenue,
COUNT(DISTINCT customer_id) AS unique_customers
FROM 'data/**/*.parquet'
WHERE year = 2024
GROUP BY category
ORDER BY total_revenue DESC
""").df() # .df() → pandas, .pl() → polars
When to use each
Use pandas when: dataset fits in memory (<500MB), team already knows it, or you need pandas-only libraries.
Use Polars when: dataset >1GB, ETL pipeline where performance matters, or multi-core parallelism is needed.
Use DuckDB when: SQL over local files, or complex JOINs across multiple sources without a database server.
References
- Vink, R. Polars: Blazingly fast DataFrames. 2024. Available at: pola.rs
- McKinney, W. Data Structures for Statistical Computing in Python. SciPy 2010 Proceedings, pp. 56–61, 2010.
- DuckDB Foundation. DuckDB Documentation. 2024. Available at: duckdb.org
- H2O.ai. Database-like ops benchmark. GitHub: h2oai/db-benchmark, 2023. Available at: github.com
- PyPI Stats. pandas download statistics. 2024. Available at: pypistats.org
Por qué pandas aún domina — y cuándo falla
Con más de 300 millones de descargas mensuales en PyPI [5], pandas es la herramienta de facto para manipulación de datos en Python. Los problemas comienzan cuando los datasets crecen: pandas usa solo un core de CPU, copia datos en memoria frecuentemente, y ejecuta operaciones sin optimización de plan de ejecución.
Polars: construido para el hardware moderno
Polars fue creado por Ritchie Vink en 2021 [1]. Escrito en Rust, usa Apache Arrow como formato en memoria y paralelismo automático. Su superpoder real es la evaluación perezosa (lazy evaluation): construye un plan de ejecución lógico y lo optimiza antes de ejecutar.
import polars as pl
# Lazy: construye un plan, no ejecuta nada aún
lf = (
pl.scan_csv("ventas_2024.csv")
.filter(pl.col("valor") > 1000)
.group_by("producto")
.agg([
pl.col("valor").sum().alias("ingreso_total"),
pl.col("cantidad").mean().alias("cantidad_media"),
])
.sort("ingreso_total", descending=True)
)
df = lf.collect() # Ejecuta el plan optimizado
Benchmarks: números reales de rendimiento
DuckDB: SQL analytics dentro de Python
DuckDB es una base de datos OLAP embebida que corre directamente en Python [3]. Ideal para analytics sobre archivos locales CSV/Parquet/JSON con SQL puro, sin servidor, sin configuración.
¿Cuándo usar cada uno?
Usa pandas: dataset <500MB, equipo ya lo conoce, o necesitas librerías que solo aceptan pandas.
Usa Polars: dataset >1GB, pipeline ETL donde el rendimiento importa, paralelismo multi-core.
Usa DuckDB: SQL sobre archivos locales, o JOINs complejos sin servidor de base de datos.
Referencias
- Vink, R. Polars: Blazingly fast DataFrames. 2024. Disponible en: pola.rs
- McKinney, W. Data Structures for Statistical Computing in Python. SciPy 2010, pp. 56–61, 2010.
- DuckDB Foundation. DuckDB Documentation. 2024. Disponible en: duckdb.org
- H2O.ai. Database-like ops benchmark. GitHub: h2oai/db-benchmark, 2023.
- PyPI Stats. Estadísticas de descargas de pandas. 2024. Disponible en: pypistats.org