← Voltar ao blog
Python Análise de Dados Performance

Polars vs Pandas: A Revolução Silenciosa do Python para Dados

O Polars é construído em Rust, usa lazy evaluation e paralelismo nativo — e é até 10× mais rápido que o pandas em operações reais. Mas isso significa que você deve abandonar o pandas agora? A resposta é mais nuançada do que parece.

MA
Allen87 Data Engineer
5 Mar 2025 · 10 min de leitura

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:

5–10×Polars é mais rápido que pandas em groupby operations (5GB dataset)
3–8×Speedup em operações de join com Polars vs pandas
~60%Menos uso de memória RAM com Polars vs pandas (mesmo dataset)

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 é:

  1. Identifique os gargalos: Use %timeit no Jupyter ou cProfile para encontrar as operações mais lentas.
  2. Migre as etapas de transformação pesada: groupby, join, filter em datasets grandes são os candidatos principais.
  3. Mantenha pandas na interface: Converta de/para pandas apenas nos pontos de integração com outras bibliotecas.
  4. 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

  1. Vink, R. Polars: Blazingly fast DataFrames in Rust, Python, Node.js, and more. Polars Documentation, 2024. Disponível em: pola.rs
  2. McKinney, W. Data Structures for Statistical Computing in Python. Proceedings of the 9th Python in Science Conference (SciPy 2010), pp. 56–61, 2010.
  3. DuckDB Foundation. DuckDB Documentation: An in-process SQL OLAP database management system. 2024. Disponível em: duckdb.org
  4. H2O.ai. Database-like ops benchmark. GitHub: h2oai/db-benchmark, 2023. Disponível em: github.com/h2oai/db-benchmark
  5. PyPI Stats. pandas download statistics. 2024. Disponível em: pypistats.org

Leia também