Polars é uma biblioteca de DataFrames orientada a expressões, com execução eager e lazy. A resposta rápida: use pl.DataFrame para exploração imediata e pl.scan_* com LazyFrame para pipelines em arquivos, nos quais o otimizador pode antecipar filtros e selecionar somente colunas necessárias. Compare com Pandas usando sua carga real, não uma promessa genérica de velocidade.
O modelo fica mais claro quando você pensa em colunas e expressões, não em loops por linha. Uma expressão descreve uma transformação; Polars combina expressões independentes e preserva um plano legível. O guia oficial do Polars é a referência para conceitos, enquanto a API Python do Polars documenta assinaturas e tipos atuais.
Instalação e primeiro DataFrame
Crie um ambiente isolado, seguindo o guia de venv em Python, e instale a biblioteca:
python -m pip install polars
O exemplo calcula receita válida por região sem alterar o DataFrame original:
import polars as pl
sales = pl.DataFrame(
{
"region": ["sul", "norte", "sul", "norte"],
"units": [2, 1, 3, 4],
"unit_price": [19.90, 35.00, 19.90, 12.50],
"cancelled": [False, False, True, False],
}
)
summary = (
sales
.filter(~pl.col("cancelled"))
.with_columns(
(pl.col("units") * pl.col("unit_price"))
.round(2)
.alias("revenue")
)
.group_by("region")
.agg(
pl.col("revenue").sum().alias("total_revenue"),
pl.len().alias("orders"),
)
.sort("total_revenue", descending=True)
)
print(summary)
pl.col não busca uma série imediatamente: constrói uma expressão. with_columns adiciona ou substitui colunas; group_by().agg() declara agregações. Valores ausentes são null, enquanto NaN é um valor de ponto flutuante distinto. Trate cada caso explicitamente com fill_null, drop_nulls ou operações de NaN adequadas.
Tipos e esquemas importam
Inferência é conveniente na exploração, mas produção deve controlar schema nas fronteiras. Datas lidas como texto, inteiros misturados a valores vazios e identificadores interpretados como números geram erros silenciosos de negócio. Inspecione DataFrame.schema, informe tipos na leitura quando necessário e use cast com uma política consciente para valores inválidos.
Não transforme tudo em texto para evitar erros: isso apenas adia o problema e prejudica filtros, datas e agregações. Tampouco use map_elements como primeira opção. Funções Python por elemento impedem várias otimizações e costumam ser menos claras que expressões nativas. Para fundamentos do ecossistema numérico, veja NumPy em Python.
Lazy API: descrever antes de executar
read_parquet produz um DataFrame eager. scan_parquet cria um LazyFrame: as transformações formam um plano e collect() dispara a execução. Isso possibilita projection pushdown e predicate pushdown: ler apenas colunas selecionadas e, quando o formato permite, evitar dados que não passam pelo filtro.
import polars as pl
report = (
pl.scan_parquet("data/sales/*.parquet")
.filter(pl.col("date") >= pl.date(2026, 1, 1))
.select("date", "region", "units", "unit_price")
.with_columns(
(pl.col("units") * pl.col("unit_price")).alias("revenue")
)
.group_by("region")
.agg(pl.col("revenue").sum().alias("revenue"))
.sort("revenue", descending=True)
)
print(report.explain())
result = report.collect()
result.write_parquet("output/revenue_by_region.parquet")
O diretório de saída deve existir. explain() ajuda a verificar o plano sem executar o pipeline completo. Evite collect() no meio de cada etapa: isso materializa resultados, quebra oportunidades de otimização e aumenta memória. Colete na fronteira em que o resultado realmente será consumido ou gravado.
CSV não oferece as mesmas possibilidades de poda que Parquet, embora a Lazy API ainda organize o plano. Escolha formatos conforme interoperabilidade, tipos, compressão e padrão de acesso. O guia de arquivos CSV e JSON com Python contextualiza formatos textuais.
Polars versus Pandas sem falsa disputa
Pandas possui ecossistema maduro, grande base de conhecimento e integração direta com inúmeras bibliotecas. Polars oferece expressões, paralelismo interno e um planejador lazy que podem ser vantajosos em pipelines analíticos. Isso não implica que toda tarefa será mais rápida nem que uma migração sempre se paga.
Compare resultados equivalentes: mesmos tipos, tratamento de nulos, ordenação, entrada e saída. Decida se o cronômetro inclui leitura, conversão e gravação. Aqueça caches quando isso representar produção, repita execuções e observe memória, não apenas o menor tempo. Registre versões, hardware e tamanho dos dados. Um microbenchmark de soma não representa um ETL com joins e arquivos.
Se Pandas já atende o volume, a equipe o domina e dependências esperam seus objetos, permanecer nele pode ser a escolha responsável. Consulte o guia de Pandas antes de comparar APIs. Se o gargalo está em um pipeline de colunas e arquivos, experimente Polars em uma etapa isolada e meça o custo de conversão nas fronteiras.
Joins, ordenação e resultados reproduzíveis
Como Polars não usa índice implícito no estilo Pandas, mantenha chaves em colunas. Antes de um join, confirme tipo, unicidade e cardinalidade esperada de cada chave. Duplicatas podem multiplicar linhas legitimamente, mas também revelar um erro de modelagem. Renomeie colunas ambíguas e selecione apenas o necessário.
Não presuma ordem se ela não foi solicitada. Após agrupamentos e joins, aplique sort quando a saída precisa ser estável para teste ou apresentação. Em agregações, defina como nulos devem participar. Essas decisões são de negócio, não detalhes da biblioteca.
Boas práticas e erros comuns
- Prefira expressões nativas a loops,
iter_rowse UDFs Python. - Use LazyFrame para pipelines de leitura, transformação e escrita.
- Colete uma vez, perto da fronteira de consumo.
- Controle schemas e normalize chaves antes de joins.
- Não converta repetidamente entre Polars, Pandas e NumPy.
- Não suponha que streaming cabe em qualquer operação; confirme suporte no plano e versão usados.
- Não compare desempenho com dados, tipos ou resultados diferentes.
- Teste pequenas tabelas com nulos, duplicatas, datas limite e categorias desconhecidas.
Checklist de adoção
- Identifique o gargalo com perfil e estabeleça uma saída correta de referência.
- Faça um protótipo representativo, incluindo I/O e conversões.
- Escolha eager para interação simples e lazy para um plano otimizável.
- Defina schema, regras de nulos, chaves, ordenação e arredondamento.
- Inspecione
explain()e elimine materializações intermediárias desnecessárias. - Meça tempo e memória em ambiente semelhante à produção.
- Verifique compatibilidade com visualização, machine learning e armazenamento.
- Cubra transformações com testes; o guia de pytest oferece a base.
Polars é uma ferramenta sólida para análise e transformação de dados, não uma obrigação universal. Uma adoção bem-sucedida começa com semântica correta, pipeline legível e medição reproduzível; a escolha da biblioteca vem depois.