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_rows e 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.