Polars - Biblioteca de DataFrame Rápida - Guia de Referência
Polars é uma biblioteca de alto desempenho DataFrame escrita em Rust com bindings para Python, R e Node. É multi-threaded por padrão, construída em Apache Arrow columnar memory e oferece uma API lazy com um otimizador de consulta que reordena e poda trabalho antes de executar. Em grandes conjuntos de dados é tipicamente muitas vezes mais rápida que pandas e usa menos memória, enquanto sua API de expressão compõe mais limpo. Tornou-se a recomendação padrão para novo trabalho com dados em 2026.
Instalação
| Método | Comando |
|---|
| pip | pip install polars |
| uv | uv add polars |
| Com extras | pip install "polars[all]" (excel, database, plotting) |
| Verificar | python -c "import polars as pl; print(pl.__version__)" |
Leitura & Escrita
| Operação | Código |
|---|
| CSV | pl.read_csv("data.csv") |
| Parquet | pl.read_parquet("data.parquet") |
| JSON | pl.read_json("data.json") |
| Banco de dados | pl.read_database(query, connection) |
| CSV Lazy | pl.scan_csv("data.csv") (diferido) |
| Parquet Lazy | pl.scan_parquet("*.parquet") |
| Escrita | df.write_parquet("out.parquet") |
Eager vs Lazy (a ideia-chave)
import polars as pl
# Eager: executa imediatamente
df = pl.read_csv("sales.csv")
result = df.filter(pl.col("amount") > 100).group_by("region").agg(pl.col("amount").sum())
# Lazy: constrói um plano, otimiza, depois executa em .collect()
result = (
pl.scan_csv("sales.csv")
.filter(pl.col("amount") > 100)
.group_by("region")
.agg(pl.col("amount").sum())
.collect()
)
Modo lazy deixa o otimizador empurrar filtros para o scan e ler apenas colunas necessárias — frequentemente um grande speedup em arquivos grandes. Prefira scan_* + .collect() para cargas de trabalho reais.
Expressões (a API central)
| Expressão | Faz |
|---|
pl.col("x") | Referência uma coluna |
pl.col("x").sum() | Agrega |
pl.col("x").alias("y") | Renomeia saída |
pl.col("*") | Todas as colunas |
pl.lit(5) | Valor literal |
pl.when(cond).then(a).otherwise(b) | Condicional |
Selecionando & Filtrando
| Tarefa | Código |
|---|
| Selecionar colunas | df.select("a", "b") |
| Coluna computada | df.with_columns((pl.col("a") * 2).alias("a2")) |
| Filtrar linhas | df.filter(pl.col("a") > 10) |
| Múltiplas condições | df.filter((pl.col("a") > 10) & (pl.col("b") == "x")) |
| Head/tail | df.head(10), df.tail(10) |
| Ordenar | df.sort("a", descending=True) |
| Único | df.unique(subset=["a"]) |
Agregação & Agrupamento
(df.group_by("region")
.agg(
pl.col("amount").sum().alias("total"),
pl.col("amount").mean().alias("avg"),
pl.col("order_id").n_unique().alias("orders"),
))
| Agregação | Expressão |
|---|
| Sum/mean/min/max | .sum(), .mean(), .min(), .max() |
| Contagem | .count(), .n_unique() |
| Primeiro/último | .first(), .last() |
| Quantil | .quantile(0.95) |
| Coletar lista | .implode() |
Joins
| Tipo | Código |
|---|
| Inner | a.join(b, on="id") |
| Esquerda | a.join(b, on="id", how="left") |
| Completo | a.join(b, on="id", how="full") |
| Anti | a.join(b, on="id", how="anti") |
| Semi | a.join(b, on="id", how="semi") |
| As-of (tempo) | a.join_asof(b, on="ts") |
Strings, Datas, Listas
| Namespace | Exemplo |
|---|
.str | pl.col("s").str.to_uppercase(), .str.contains("x") |
.dt | pl.col("t").dt.year(), .dt.truncate("1h") |
.list | pl.col("l").list.len(), .list.first() |
.cast | pl.col("a").cast(pl.Int64) |
Interop
| Alvo | Código |
|---|
| pandas | df.to_pandas() / pl.from_pandas(pdf) |
| Arrow | df.to_arrow() |
| NumPy | df.to_numpy() |
| DuckDB | Consultar frames Polars diretamente de DuckDB |
Polars vs pandas
| Aspecto | Polars | pandas |
|---|
| Motor | Rust, multi-threaded | Python/C, principalmente single-threaded |
| Memória | Arrow columnar | NumPy-backed |
| Otimizador lazy | Sim | Não |
| API | Baseada em expressão, componível | Baseada em índice |
| Ecossistema | Crescendo rápido | Vasto, maduro |
Para análise SQL-first sobre arquivos, combine com DuckDB; pandas permanece valioso por sua amplitude de ecossistema.
Recursos