Polars em Python: A Alternativa Rápida ao Pandas — 2026 | Python Brasil
Conheça o Polars, a biblioteca Python escrita em Rust para DataFrames ultrarrápidos. Comparação com Pandas, benchmarks, exemplos práticos e guia de migração.
Se você trabalha com dados em Python, provavelmente já usa o Pandas no dia a dia. Ele é a biblioteca padrão para manipulação de DataFrames há mais de uma década. Mas nos últimos anos, uma alternativa vem ganhando espaço rapidamente: o Polars — uma biblioteca de DataFrames escrita em Rust, projetada para ser extremamente rápida e eficiente em memória.
Neste artigo, vamos explorar o que torna o Polars especial, comparar com o Pandas em benchmarks reais, e mostrar como começar a usá-lo nos seus projetos.
O Que É o Polars
Polars é uma biblioteca open-source para manipulação de dados tabulares em Python (e também em Rust e Node.js). Diferente do Pandas, que é implementado em Python/C, o Polars foi escrito do zero em Rust — a mesma linguagem por trás de ferramentas modernas como Ruff e uv.
As características principais do Polars incluem:
- Execução paralela automática — utiliza todos os núcleos do processador sem configuração extra
- Avaliação lazy (preguiçosa) — otimiza queries antes de executá-las
- Consumo de memória eficiente — usa Apache Arrow como formato interno
- API expressiva — baseada em expressões encadeáveis e composíveis
- Sem dependência do NumPy — funciona de forma independente
Instalação
Para instalar o Polars, o ideal é usar um ambiente virtual dedicado. Com uv:
# Terminal
uv pip install polars
# Ou com pip tradicional
pip install polars
Para funcionalidades extras como leitura de Excel e conexão com bancos de dados:
pip install 'polars[all]'
Polars vs Pandas: Benchmark de Performance
Vamos comparar as duas bibliotecas em uma operação comum — ler um CSV, filtrar linhas e agrupar dados:
import time
import pandas as pd
import polars as pl
# Gerando dados de exemplo (1 milhão de linhas)
import numpy as np
np.random.seed(42)
n = 1_000_000
dados = {
"cidade": np.random.choice(["São Paulo", "Rio", "Curitiba", "BH", "Salvador"], n),
"categoria": np.random.choice(["A", "B", "C"], n),
"valor": np.random.uniform(10, 1000, n),
"quantidade": np.random.randint(1, 100, n),
}
# --- Pandas ---
inicio = time.perf_counter()
df_pd = pd.DataFrame(dados)
resultado_pd = (
df_pd[df_pd["valor"] > 100]
.groupby(["cidade", "categoria"])
.agg({"valor": "mean", "quantidade": "sum"})
)
tempo_pandas = time.perf_counter() - inicio
# --- Polars ---
inicio = time.perf_counter()
df_pl = pl.DataFrame(dados)
resultado_pl = (
df_pl.filter(pl.col("valor") > 100)
.group_by(["cidade", "categoria"])
.agg(
pl.col("valor").mean(),
pl.col("quantidade").sum(),
)
)
tempo_polars = time.perf_counter() - inicio
print(f"Pandas: {tempo_pandas:.3f}s")
print(f"Polars: {tempo_polars:.3f}s")
print(f"Polars foi {tempo_pandas / tempo_polars:.1f}x mais rápido")
Em testes típicos com 1 milhão de linhas, o Polars costuma ser 3x a 10x mais rápido que o Pandas nesse tipo de operação. A diferença aumenta conforme o dataset cresce, especialmente por causa do paralelismo automático.
Lazy vs Eager: O Poder da Avaliação Preguiçosa
Uma das maiores vantagens do Polars é o modo lazy. Em vez de executar cada operação imediatamente (modo eager, como o Pandas faz), o Polars constrói um plano de execução e otimiza tudo antes de rodar:
import polars as pl
# Modo lazy — nada é executado ainda
query = (
pl.scan_csv("vendas.csv") # scan_ em vez de read_
.filter(pl.col("status") == "concluída")
.filter(pl.col("valor") > 50)
.group_by("produto")
.agg(
pl.col("valor").sum().alias("total_vendas"),
pl.col("valor").count().alias("num_vendas"),
)
.sort("total_vendas", descending=True)
.head(10)
)
# Agora sim, executa com otimizações
resultado = query.collect()
print(resultado)
O otimizador do Polars pode, por exemplo, combinar os dois filter em um só, aplicar projeção de colunas (ler apenas as colunas necessárias do CSV) e reordenar operações para minimizar o uso de memória. Isso faz uma diferença enorme com arquivos grandes.
API de Expressões: A Filosofia do Polars
O Polars usa um sistema de expressões que é diferente do Pandas. Em vez de acessar colunas como atributos ou usar .apply(), você compõe expressões com pl.col():
import polars as pl
df = pl.DataFrame({
"nome": ["Ana", "Bruno", "Carla", "Diego", "Eva"],
"idade": [28, 35, 42, 31, 26],
"salario": [5500, 8200, 12000, 7100, 4800],
"departamento": ["TI", "TI", "Gestão", "TI", "Gestão"],
})
# Expressões encadeáveis e composíveis
resultado = df.select(
pl.col("nome"),
pl.col("salario").alias("salario_atual"),
(pl.col("salario") * 1.10).round(2).alias("salario_reajustado"),
pl.col("idade").mean().over("departamento").alias("idade_media_dept"),
pl.when(pl.col("salario") > 7000)
.then(pl.lit("Sênior"))
.otherwise(pl.lit("Pleno"))
.alias("nivel"),
)
print(resultado)
Esse estilo baseado em expressões é mais declarativo e permite que o Polars otimize internamente cada operação. Se você já programa com boas práticas Python, vai perceber que o código fica limpo e legível.
Leitura de Diferentes Formatos
O Polars suporta vários formatos de arquivo nativamente:
import polars as pl
# CSV
df = pl.read_csv("dados.csv")
# Parquet (formato colunar, ideal para big data)
df = pl.read_parquet("dados.parquet")
# JSON
df = pl.read_json("dados.json")
# Lazy scan — não carrega tudo na memória
lazy_df = pl.scan_parquet("dados_grandes.parquet")
# Escrita
df.write_parquet("saida.parquet")
df.write_csv("saida.csv")
O formato Parquet merece destaque especial. Como é colunar e comprimido, o Polars consegue ler apenas as colunas necessárias no modo lazy, economizando memória e tempo de I/O.
Joins e Operações Comuns
Operações de join são frequentes em ciência de dados. Veja como funcionam no Polars:
import polars as pl
clientes = pl.DataFrame({
"id_cliente": [1, 2, 3, 4],
"nome": ["Ana", "Bruno", "Carla", "Diego"],
"cidade": ["SP", "RJ", "SP", "BH"],
})
pedidos = pl.DataFrame({
"id_pedido": [101, 102, 103, 104, 105],
"id_cliente": [1, 2, 1, 3, 2],
"valor": [150.0, 200.0, 75.0, 320.0, 180.0],
})
# Join
resultado = clientes.join(pedidos, on="id_cliente", how="left")
# Agregação após join
resumo = (
resultado
.group_by("nome", "cidade")
.agg(
pl.col("valor").sum().alias("total_gasto"),
pl.col("id_pedido").count().alias("num_pedidos"),
)
.sort("total_gasto", descending=True)
)
print(resumo)
Quando Usar Polars vs Pandas
Nem sempre o Polars é a melhor escolha. Aqui vai um guia prático:
Use Polars quando:
- Seu dataset tem mais de 100 mil linhas
- Você precisa de performance máxima
- Trabalha com arquivos Parquet
- Quer aproveitar paralelismo automático
- Está construindo pipelines de dados
Mantenha o Pandas quando:
- Seu dataset é pequeno (menos de 50 mil linhas)
- Precisa de integração com bibliotecas que exigem Pandas (scikit-learn, Matplotlib)
- Sua equipe já domina a API do Pandas
- Usa funcionalidades específicas do Pandas sem equivalente no Polars
A boa notícia é que os dois podem coexistir. O Polars oferece conversão fácil:
# Polars para Pandas
df_pandas = df_polars.to_pandas()
# Pandas para Polars
df_polars = pl.from_pandas(df_pandas)
Migrando do Pandas para o Polars
Se você já tem código em Pandas e quer migrar gradualmente, aqui estão as equivalências mais comuns:
| Pandas | Polars |
|---|---|
df["coluna"] | df.select("coluna") ou df["coluna"] |
df[df["x"] > 10] | df.filter(pl.col("x") > 10) |
df.groupby("x").agg({"y": "sum"}) | df.group_by("x").agg(pl.col("y").sum()) |
df.merge(df2, on="id") | df.join(df2, on="id") |
df.apply(func) | df.select(pl.col("x").map_elements(func)) |
df.sort_values("x") | df.sort("x") |
A dica é migrar aos poucos: comece usando Polars para leitura e processamento pesado, converta para Pandas quando precisar de compatibilidade com outras bibliotecas.
Conclusão
O Polars representa uma nova geração de ferramentas para dados em Python — mais rápido, mais eficiente e com uma API moderna. Se você trabalha com tipagem estática e boas práticas, vai apreciar a filosofia do Polars de ser explícito e composível.
Para quem está começando a explorar o ecossistema de IA e dados, vale também conferir como usar APIs de LLMs em Python — outra tendência forte do ecossistema Python em 2026.
O Polars não veio para substituir o Pandas, mas para complementá-lo. Experimente no seu próximo projeto de dados e veja a diferença de performance na prática.
Por que Rust? O Polars é escrito em Rust, a mesma linguagem por trás de ferramentas como Ruff e uv. Rust oferece performance próxima ao C com garantias de segurança de memória em tempo de compilação — o que explica a velocidade impressionante do Polars sem sacrificar a estabilidade.
Equipe python.dev.br
Contribuidor do Python Brasil — Aprenda Python em Português