Programa
No mundo da análise de dados, pandas tem sido a escolha padrão para lidar com dados tabulares em Python por profissionais de dados.
Mas, conforme os conjuntos de dados ficam maiores e mais complexos, o pandas pode ter problemas de desempenho, uso limitado de múltiplos núcleos e limitações de memória.
É aí que o Polars aparece como uma alternativa moderna. Polars é uma biblioteca DataFrame escrita em Rust que oferece um desempenho super rápido, gerenciamento de memória eficiente e uma filosofia de design focada em escalabilidade.
Neste tutorial, vamos compartilhar o que é Polars e como fazer algumas operações básicas do Polars em Python. Se você está procurando alguma experiência prática, recomendo conferir o curso Introdução aos Polares.
Principais recursos do Python Polars

O Polars tem um conjunto único de recursos que o diferenciam do pandas:
- Fundação Rust: Segurança e desempenho no nível dos sistemas.
- Execução multithread: Aproveita ao máximo as CPUs modernas.
- Avaliação preguiçosa: Adiar a execução até que seja explicitamente necessário.
- Aplicação do esquema: Garantir o tratamento consistente dos dados.
- Suporte avançado a tipos de dados: Lida com tipos temporais, categóricos e aninhados de forma nativa.
Tipos de dados no Polars
O Polars dá suporte a uma ampla variedade de tipos de dados além dos básicos:
- Numérico:
Int32,Int64,Float32,Float64. - Valores booleanos: valores
true/false. - Temporal:
Date,Datetime,Duration,Time. - : Strings codificadas para armazenamento eficiente em termos de memória.
- Tipos aninhados: tipos
ListeStruct, úteis para dados do tipo JSON.
Vantagens em relação aos pandas
Sendo a alternativa mais nova e moderna ao pandas, o Polars oferece várias vantagens:
- Execução mais rápida em grandes conjuntos de dados.
- Mais eficiente em termos de memória.
- Mais adequado para pipelines ETL e produção.
- Otimizações integradas, como empurramento de predicados e projeções.
Instalação e configuração do ambiente para Python Polars
Agora, vamos dar uma olhada em como podemos começar a usar Polars para nós mesmos em Python.
Antes de usar o Polars, você precisa configurar o ambiente corretamente.
Plataformas compatíveis
O Polars funciona no Windows, macOS e Linux. Pode ser instalado em ambientes virtuais, no sistema Python ou por meio de fluxos de trabalho em contêineres (Docker).
Instalação com o pip
Para instalar a biblioteca polars no Python, execute o seguinte comando no terminal.
pip install polars
Você deve ver a seguinte mensagem de instalação:

Instalação com o conda
Se preferir, você pode instalar a biblioteca no ambiente conda, se for isso que você está usando.
conda install -c conda-forge polars
Confira a instalação
Para ver se a instalação deu certo, escreva este script simples:
import polars as pl
print(pl.__version__)
Variáveis de configuração e ambiente
O Polars permite que você ajuste como ele funciona e como suas saídas são mostradas, definindo variáveis de ambiente antes de começar sua sessão Python. Por exemplo:
POLARS_MAX_THREADS: Limite o número de threads.POLARS_FMT_MAX_COLS: Controle o número de colunas impressas.POLARS_FMT_TABLE_WIDTH: Ajustar a largura de exibição do DataFrame.
Aqui vai um exemplo de como você definiria essas variáveis em um shell antes de rodar o Python:
export POLARS_MAX_THREADS=8
export POLARS_FMT_MAX_COLS=20
Gerando um conjunto de dados CSV de amostra para demonstração
Antes de mergulhar nas funcionalidades do Polars, é útil ter um conjunto de dados que possamos usar de forma consistente ao longo deste tutorial. A gente pode criar um arquivo CSV simples usando o módulo csv integrado do Python ou o pandas.
Aqui tá um exemplo que cria um arquivo transactions.csv com dados sintéticos:
import csv
import random
from datetime import datetime, timedelta
# Define column names
columns = ["transaction_id", "customer_id", "amount", "transaction_date"]
# Generate synthetic rows
rows = []
start_date = datetime(2023, 1, 1)
for i in range(1, 101):
customer_id = random.randint(1, 10)
amount = round(random.uniform(10, 2000), 2)
date = start_date + timedelta(days=random.randint(0, 90))
rows.append([i, customer_id, amount, date.strftime("%Y-%m-%d")])
# Write to CSV
with open("transactions.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(columns)
writer.writerows(rows)
Esse script cria um conjunto de dados com 100 transações com valores aleatórios, IDs de clientes e datas de transação. Você pode ajustar o alcance e o tamanho de acordo com suas necessidades.
Salve esse script, execute-o uma vez e você terá um arquivo CSV para usar nos exemplos ao longo deste artigo.
Conceitos básicos em DataFrame e Series polares do Python
O Polars é construído com base em duas abstrações principais: a Série e o DataFrame.
Juntos, eles oferecem uma maneira estruturada e eficiente de trabalhar com dados, parecida com o pandas, mas otimizada com o backend do Polars, que usa Rust. Vamos analisar os principais conceitos.
Série: Matrizes 1D com um tipo definido
Uma série em polares é uma matriz unidimensional, parecida com uma coluna numa planilha ou tabela de banco de dados. Cada série tem:
- Um nome (o rótulo da coluna).
- Um tipo de dados (como
Int64,Utf8,Float64,Boolean, etc.). - Uma coleção organizada de valores.
Como o tipo de dados é rigorosamente aplicado, as séries no Polars tendem a ser mais rápidas e previsíveis do que as listas do Python.
Exemplo:
import polars as pl
# Create a Series of integers
s = pl.Series("numbers", [1, 2, 3, 4, 5])
print(s)
Resultado:
shape: (5,)
Series: 'numbers' [i64]
[
1
2
3
4
5
]
DataFrame: Uma coleção de séries
Um DataFrame é uma estrutura bidimensional que organiza várias séries juntas em um esquema. É tipo uma tabela no SQL ou no Excel. As linhas são registros e as colunas são campos.
Exemplo:
df = pl.DataFrame({
"id": [1, 2, 3],
"name": ["Alice", "Bob", "Charlie"],
"age": [25, 30, 35]
})
print(df)
Resultado:
shape: (3, 3)
┌─────┬─────────┬─────┐
│ id │ name │ age │
│ --- │ --- │ --- │
│ i64 │ str │ i64 │
├─────┼─────────┼─────┤
│ 1 │ Alice │ 25 │
│ 2 │ Bob │ 30 │
│ 3 │ Charlie │ 35 │
└─────┴─────────┴─────┘
Cada coluna é uma série, e o DataFrame faz valer o seu esquema.
Papel dos esquemas e consistência rigorosa dos tipos
Um dos pontos fortes do Polars é a aplicação rigorosa do esquema. Cada coluna tem um tipo de dados fixo, e o Polars garante que todas as operações respeitem isso. Isso evita bugs sutis que surgem em operações tipadas dinamicamente.
Por exemplo, você não pode adicionar sem querer uma coluna de string a uma coluna inteira sem fazer uma conversão explícita.
Exemplo:
df = df.with_columns(
(pl.col("age") + 5).alias("age_plus_5")
)
print(df)
Aqui, age é i64, e o resultado continua sendo um número inteiro. Se você tentasse adicionar uma coluna de string, o Polars apresentaria um erro em vez de falhar silenciosamente.
Tratamento de valores nulos
Os dados do mundo real muitas vezes têm valores ausentes, e o Polars oferece ferramentas claras para lidar com eles:
fill_null(): Substitua os valores nulos por um valor específico.drop_nulls(): Tira as linhas que têm valores nulos.is_null()/is_not_null(): Verificações booleanas.
Expressões: Operações vetorizadas em colunas
O Polars promove um sistema de expressão, onde as operações são definidas como transformações em colunas, em vez de loops Python linha por linha.
Essas expressões são vetorizadas, ou seja, elas funcionam em colunas inteiras de uma vez, o que é bem mais rápido.
Em vez de fazer loops manualmente, o Polars cria um cálculo vetorizado rápido.
Ansioso vs. Execução preguiçosa
O Polars tem dois modos de execução:
1. Execução ansiosa
- Executa cálculos imediatamente.
- Parecido com os pandas.
- Ótimo para exploração interativa e conjuntos de dados pequenos a médios.
Aqui vai um exemplo de execução ansiosa:
df = pl.DataFrame({"x": [1, 2, 3]})
print(df.select(pl.col("x") * 2)) # eager: runs instantly
2. Execução preguiçosa
- Cria um plano de consulta em vez de executar imediatamente.
- O Polars otimiza esse plano nos bastidores (empurramento de predicados, paralelização, poda de projeção).
- Ótimo para grandes conjuntos de dados e transformações complexas.
Aqui vai um exemplo de execução preguiçosa:
lazy_df = pl.DataFrame({"x": [1, 2, 3]}).lazy()
result = lazy_df.select(pl.col("x") * 2).collect() # execute on collect()
print(result)
Aqui, nada é calculado até que se chame .collect(). Em fluxos de trabalho grandes, isso pode trazer melhorias incríveis no desempenho.
Operações básicas com DataFrame no Python Polars
A seguir, vamos ver como fazer algumas operações básicas usadas no Polars no conjunto de dados que criamos.
Carregando o conjunto de dados
Os Polars podem pegar dados de vários formatos de arquivo e objetos de memória. Isso torna-o flexível para integração em pipelines de dados modernos.
Veja como você pode fazer isso para diferentes fontes:
A partir do conjunto de dados CSV que criamos antes:
import polars as pl
df = pl.read_csv("transactions.csv")
print(df.head())
Também podemos ler o conjunto de dados do Parquet, se for preciso.
df_parquet = pl.read_parquet("transactions.parquet")
Se você tiver um arquivo JSON, pode lê-lo usando este código:
df_json = pl.read_json("transactions.json")
#For JSON Lines (NDJSON), use the following instead:
df_json = pl.read_ndjson("transactions.json")
Veja como você pode ler conjuntos de dados de uma tabela Arrow:
import pyarrow as pa
arrow_table = pa.table({
"transaction_id": [1, 2],
"customer_id": [5, 7],
"amount": [150.25, 300.75],
"transaction_date": ["2023-01-02", "2023-01-03"]
})
df_arrow = pl.from_arrow(arrow_table)
Selecionando e filtrando
Agora vamos escolher colunas ou linhas específicas do nosso conjunto de dados.
Selecionar colunas
Quando você usa o Polars, uma coisa comum é escolher as colunas que você quer usar e manter.
Veja como você pode fazer isso:
# Select only transaction_id and amount
df.select(["transaction_id", "amount"])
Filtrar linhas
Você também pode filtrar linhas com base nas condições que definir, parecido com o pandas.
# Get only high-value transactions above $1,000
high_value = df.filter(pl.col("amount") > 1000)
print(high_value)
Aplicar expressões
Aplicar expressões no Polars envolve usar o objeto polars.Expr em vários contextos para fazer transformações de dados.
Você pode criá-los usando pl.col() ou pl.lit().
# Add a 10% discount column to simulate promotional pricing
df.select([
pl.col("transaction_id"),
pl.col("amount"),
(pl.col("amount") * 0.9).alias("discounted_amount")
])
Agregados
A gente pode ver como os clientes gastam usando o group_by.
# Total and average spend per customer
agg_df = df.group_by("customer_id").agg([
pl.sum("amount").alias("total_spent"),
pl.mean("amount").alias("avg_transaction")
])
print(agg_df)
Exemplo de saída:
shape: (10, 3)
┌─────────────┬────────────┬───────────────┐
│ customer_id │ total_spent│ avg_transaction│
│ --- │ --- │ --- │
│ i64 │ f64 │ f64 │
├─────────────┼────────────┼───────────────┤
│ 1 │ 5230.12 │ 523.01 │
│ 2 │ 6120.45 │ 680.05 │
│ ... │ ... │ ... │
└─────────────┴────────────┴───────────────┘
Lidando com valores ausentes
Nosso conjunto de dados gerado não tem nulos por padrão, mas vamos simular como lidaríamos com eles.
Preencher valores ausentes
Valores ausentes podem causar problemas na análise posterior e na visualização dos dados. Você vai precisar preencher os valores que faltam pra garantir que tudo corra bem.
Veja como você pode preencher os valores que estão faltando:
# Imagine 'amount' has missing values, then replace with 0
df_filled = df.with_columns(
pl.col("amount").fill_null(0)
)
Eliminar valores nulos
Os nulos podem causar erros se não forem tratados. Veja como eliminá-los:
df_no_nulls = df.drop_nulls()
Tipos de conversão
Os tipos de dados podem estar formatados incorretamente em um conjunto de dados. Veja como você pode convertê-los usando o método ` .cast `:
# Ensure customer_id is treated as string instead of int
df_casted = df.with_columns(
pl.col("customer_id").cast(pl.Utf8)
)
Operações em cadeia
O Polars permite encadear métodos para fluxos de trabalho mais organizados. Esse método de encadeamento é bem comum em SQL ou programação R usando o pacote tidyverse.
Exemplo: Descubra os principais clientes em março por gasto total
pipeline = (
df
.with_columns(pl.col("transaction_date").str.strptime(pl.Date, format="%Y-%m-%d"))
#.col("date_str").str.to_date(format="%Y-%m-%d")
.filter(pl.col("transaction_date").dt.month() == 3) # transactions in March
.group_by("customer_id")
.agg(pl.sum("amount").alias("march_spent"))
.sort("march_spent", descending=True)
)
print(pipeline)
Este pipeline:
- Filtra as transações de março.
- Grupos por cliente.
- Gastos agregados.
- Classifica por gasto total.
Esse método de encadeamento permite que uma análise de pipeline seja feita sem usar DataFrame intermediários.
Recursos avançados e avaliação preguiçosa em Polars
Além do básico, o Polars se destaca ao trabalhar com grandes conjuntos de dados graças ao seu mecanismo de avaliação preguiçosa. Esse modelo permite que o Polars crie primeiro um plano de consulta, otimize-o internamente e só depois execute o pipeline. O resultado é um grande aumento no desempenho e na eficiência, principalmente com milhões de linhas ou transformações complexas.
Por padrão, o Polars funciona no modo eager. Isso quer dizer que os cálculos rolam na hora, tipo no pandas. O modo preguiçoso, no entanto, funciona de forma diferente:
- Cada operação (filtro, seleção, agrupamento) é registrada em vez de ser executada imediatamente.
- As transformações só rolam quando você chama o
.collect(). - Isso adia o trabalho até que o Polars possa analisar todo o pipeline e executá-lo da maneira mais eficiente possível.
Aqui vai um exemplo do modo preguiçoso:
import polars as pl
# Load dataset in lazy mode
lazy_df = pl.scan_csv("transactions.csv")
# Build a transformation pipeline
pipeline = (
lazy_df
.filter(pl.col("amount") > 1000) # step 1: filter expensive transactions
.group_by("customer_id") # step 2: group by customer
.agg(pl.sum("amount").alias("total_spent")) # step 3: aggregate
)
# Nothing has run yet, computation happens only on collect()
result = pipeline.collect()
print(result)
Otimização de consultas
O Polars otimiza as consultas usando técnicas de pushdown:
- Empurrão de predicado: Os filtros são colocados o mais próximo possível da fonte de dados. Exemplo: Ao filtrar
amount > 1000, o Polars aplica esse filtro enquanto lê o CSV, em vez de depois de carregar todas as linhas. - Empurrão de projeção: Só as colunas que você precisa são lidas na memória. Exemplo: Se você selecionar apenas
customer_ideamount, o Polars vai ignorar completamente a leitura detransaction_date.
Streaming para grandes volumes de dados
Quando os dados são grandes demais para caber na memória, o Polars oferece execução em streaming. Em vez de carregar tudo de uma vez, o Polars processa os dados em lotes, mantendo o uso da memória estável.
Isso é super útil pra arquivos CSV ou Parquet com vários GB.
Exemplo (modo streaming):
# Enable streaming execution for huge datasets
stream_result = (
lazy_df
.group_by("customer_id")
.agg(pl.sum("amount").alias("total_spent"))
.collect(streaming=True) # execute in streaming mode
)
Com o streaming=True, o Polars evita criar tabelas intermediárias enormes na memória, o que o torna mais escalável do que o pandas para grandes cargas de trabalho.
Execução com .collect() e Depuração de Consultas Lazy
O método ` .collect() ` é o gatilho para executar um pipeline preguiçoso. Antes disso, você pode dar uma olhada e corrigir o plano de consulta com:
.describe_plan(): Mostra o plano lógico..describe_optimized_plan(): Mostra o plano otimizado depois que o Polars aplica pushdowns e simplificações.
Otimizando o desempenho e a eficiência do Python Polars
Os polares podem ajudar a melhorar o desempenho na execução de seus pipelines de análise.
Aqui estão algumas dicas:
- Use avaliação preguiçosa para pipelines grandes.
- Minimize a conversão de tipos.
- Evite a materialização desnecessária de DataFrame intermediários.
Junções, fusões e combinações de dados no Python Polars
A análise do mundo real muitas vezes precisa juntar conjuntos de dados. O Polars oferece um conjunto completo de operações de junção com execução otimizada, facilitando a fusão até mesmo de tabelas grandes.
Junções suportadas
O Polars aceita todos os principais tipos de junção:
- Inner Join: Guarde só as linhas que combinam.
- União à esquerda/direita: Mantenha todas as linhas de um lado.
- : Mantenha todas as linhas, preenchendo as lacunas com nulos.
- Semi Join: Mantenha as linhas da esquerda que têm uma correspondência à direita.
- Anti Join: Mantenha as linhas da esquerda que não têm correspondência à direita.
- : Produto cartesiano das duas tabelas.
Exemplo: Juntando transações com metadados do cliente
# Create customer metadata DataFrame
customers = pl.DataFrame({
"customer_id": [1, 2, 3, 4, 5],
"customer_name": ["Alice", "Bob", "Charlie", "David", "Eva"]
})
# Inner join on customer_id
df_joined = df.join(customers, on="customer_id", how="inner")
print(df_joined.head())
Polars e Pandas se juntam para melhorar o desempenho e a usabilidade
O Polars é melhor que o Pandas nas duas áreas:
- Desempenho: As junções polares são implementadas em Rust com paralelismo, tornando-as mais rápidas em grandes conjuntos de dados do que o pandas. O empurrão de predicado e projeção também se aplica às junções, reduzindo a movimentação desnecessária de dados.
- Usabilidade: O Polars precisa de chaves de junção explícitas, o que evita junções acidentais no alinhamento do índice (uma armadilha comum no pandas). Semi e anti joins são nativos no Polars, enquanto no pandas eles precisam de soluções alternativas.
Funções de janela e operações contínuas em polares
As funções de janela permitem cálculos dentro de grupos ou em linhas ordenadas, sem colapsar os resultados, de forma semelhante às funções de janela SQL.
O Polars permite calcular estatísticas por cliente ou por período de tempo usando contextos de janela.
Aqui estão alguns exemplos de funções de janela que você pode usar no Polars:
- Média móvel/soma para médias móveis.
- Expandindo janelas para estatísticas acumuladas.
- Funções de classificação para análises baseadas em pedidos.
1. Funções em execução
Exemplo: Totais acumulados do cliente
df_window = df.with_columns( pl.col("amount") .sort_by("transaction_date") .cum_sum() .over("customer_id") .alias("running_total") )
print(df_window.head())
2. Funções contínuas
As funções rolantes funcionam em uma janela deslizante de linhas ou tempo.
Exemplo: Soma acumulada das transações dos últimos 7 dias
df = df.with_columns(pl.col("transaction_date").str.strptime(pl.Date, format="%Y-%m-%d")
rolling = (
df.group_by_rolling("transaction_date", period="7d")
.agg(pl.sum("amount").alias("rolling_7d_sum"))
)
print(rolling.head())
Janelas expansíveis (cumulativas) e janelas alinhadas ao centro também são suportadas através do ajuste de parâmetros.
3. Funções de classificação
Você pode usar funções de classificação e agregações personalizadas dentro das janelas.
Exemplo: Classifique as transações por cliente de acordo com o valor
ranked = df.with_columns(
pl.col("amount").rank("dense", descending=True).over("customer_id").alias("rank")
)
print(ranked.head())
Isso gera classificações (1 = mais alto) para os gastos de cada cliente.
As funções de janela permitem cálculos contextuais:
print(
df.group_by("customer_id").agg(pl.col("amount").cum_sum().alias("cumulative_spent"))
)
Usando consultas SQL no Python Polars
Para analistas acostumados com SQL, o Polars oferece um contexto SQL para que você possa consultar DataFrame diretamente com a sintaxe SQL, sem deixar de aproveitar a velocidade do Polars.
Registro de contexto SQL e DataFrame
Pra começar, você precisa registrar um DataFrame antes de rodar o SQL.
from polars import SQLContext
ctx = SQLContext()
ctx.register("transactions", df)
Executando consultas SQL diretamente no Polars
Vamos ver um exemplo de como executar uma consulta SQL no Python usando o Polars.
Exemplo: Consultar o gasto total por cliente em SQL
result = ctx.execute("""
SELECT customer_id, SUM(amount) AS total_spent
FROM transactions
GROUP BY customer_id
ORDER BY total_spent DESC
""").collect()
print(result)
Integrando SQL com expressões Polars
Você pode misturar SQL e expressões:
sql_result = ctx.execute("SELECT * FROM transactions WHERE amount > 1500")
df_sql = sql_result.collect()
# Continue with Polars expressions
df_sql = df_sql.with_columns((pl.col("amount") * 0.95).alias("discounted"))
Isso é útil para equipes que estão mudando de ferramentas baseadas em SQL.
Integração do Polars Python com o ecossistema mais amplo
O Polars não foi feito pra ser uma ilha isolada, mas sim uma biblioteca DataFrame de alto desempenho que funciona bem com o ecossistema de dados Python mais amplo. Essa interoperabilidade garante que analistas e engenheiros possam adotar o Polars aos poucos, sem deixar de usar as ferramentas que já têm.
Aqui estão algumas áreas de integração:
- Interoperabilidade de pacotes: Converta facilmente entre Polars, pandas, NumPy e Arrow.
- Visualização: Use matplotlib, seaborn ou plotly para criar gráficos.
- machine learning: Insira DataFrame Polares em pipelines scikit-learn, PyTorch ou TensorFlow.
- e de nuvem e banco de dados: E/S eficiente com Parquet, Arrow e conectores para armazenamento em nuvem.
- Notebooks Jupyter: O Polars se integra perfeitamente em ambientes interativos.
Exemplos e casos de uso comuns do Python Polars
Por fim, vamos dar uma olhada rápida em alguns exemplos de uso do Polars:
1. Limpeza de dados
df = df.with_columns([
pl.col("transaction_date").str.strptime(pl.Date, "%Y-%m-%d").alias("txn_date"),
pl.col("amount").fill_null(strategy="mean")
])
2. Pipelines ETL
result = (
pl.read_csv("transactions.csv")
.lazy()
.filter(pl.col("amount") > 1000)
.group_by("customer_id")
.agg(pl.sum("amount").alias("total_spent"))
.collect()
)
3. Finanças
Aqui está um exemplo de médias móveis para valores de transações.
import polars as pl
# Load & parse dates
df = (
pl.read_csv("transactions.csv")
.with_columns(pl.col("transaction_date").str.strptime(pl.Date, "%Y-%m-%d"))
)
# (A) Overall: daily totals + 7-day rolling average
daily = (
df.sort("transaction_date")
.group_by_dynamic("transaction_date", every="1d")
.agg(pl.sum("amount").alias("daily_total"))
.sort("transaction_date")
.with_columns(
pl.col("daily_total").rolling_mean(window_size=7).alias("ma7")
)
)
# (B) Per-customer: daily totals + 7-day rolling average within each customer
daily_by_cust = (
df.sort("transaction_date")
.group_by_dynamic(index_column="transaction_date", every="1d", by="customer_id")
.agg(pl.sum("amount").alias("daily_total"))
.sort(["customer_id", "transaction_date"])
.with_columns(
pl.col("daily_total")
.rolling_mean(window_size=7)
.over("customer_id")
.alias("ma7_per_customer")
)
)
print(daily.tail())
print(daily_by_cust.filter(pl.col("customer_id")==1).tail())
Aqui está o resultado esperado:

4. Computação científica
Ao fazer cálculos científicos, você vai precisar lidar com milhões de linhas de dados experimentais ou simulados, tipo transações, de forma eficiente.
Aqui está um exemplo de implementação:
import polars as pl
# Assume a very large Parquet file with columns: id, value, ts (UTC)
# Use lazy scan_* to avoid loading into memory up-front
lazy = (
pl.scan_parquet("experiments.parquet") # or: pl.scan_csv("experiments.csv")
.filter(pl.col("value") > 0) # predicate pushdown
.select(["id", "value", "ts"]) # projection pushdown
.with_columns(
# Example transformations: standardization & bucketize timestamps by hour
((pl.col("value") - pl.col("value").mean()) / pl.col("value").std())
.alias("z_value"),
pl.col("ts").dt.truncate("1h").alias("ts_hour")
)
.group_by(["id", "ts_hour"])
.agg([
pl.len().alias("n"),
pl.mean("z_value").alias("z_mean"),
pl.std("z_value").alias("z_std")
])
.sort(["id", "ts_hour"])
)
# Execute in streaming mode to keep memory usage low
result = lazy.collect(streaming=True)
# Optionally write out partitioned Parquet for downstream analysis
result.write_parquet("experiments_hourly_stats.parquet")
print(result.head())
Considerações finais
O Python Polars oferece uma biblioteca DataFrame moderna e de alto desempenho que resolve muitas das limitações do pandas. Embora o pandas continue sendo popular para análises menores e ad hoc, o Polars está cada vez mais se tornando a ferramenta preferida para o processamento de dados escalável, eficiente e confiável em Python.
Quer saber mais sobre os Polars? Você vai curtir nosso curso de curso Introdução às Polares ou nosso Introdução aos Polares. Nossos Polars Engine também pode te interessar.
Perguntas frequentes sobre os polares Python
Quais são as principais diferenças entre Polars e Pandas?
O Polars é mais rápido e usa menos memória porque foi feito em Rust e usa um mecanismo baseado em colunas. Ele suporta os modos lazy e eager, enquanto o pandas só funciona no modo eager. O Pandas é mais fácil de usar para tarefas pequenas, mas o Polars é melhor para big data e desempenho.
Como o Polars lida com grandes conjuntos de dados em comparação com o Pandas?
Os Polars podem processar arquivos grandes sem precisar carregar tudo na memória de uma vez só. Ele lê só as colunas e linhas necessárias e faz as operações em paralelo. O Pandas carrega todo o conjunto de dados na memória e geralmente funciona em um único thread, o que pode ser mais lento e pesado.
Você pode explicar o conceito de avaliação preguiçosa no Polars?
Avaliação preguiçosa significa que você primeiro descreve o que quer fazer, e o Polars espera para executá-lo. Quando você chama um .collect(), o Polars executa todas as etapas de uma vez só, de um jeito otimizado. Isso torna o processo mais rápido, pois evita trabalho extra e reduz o uso de memória.
Quais são algumas técnicas avançadas de manipulação de dados no Polars?
Os polares podem fazer médias móveis, funções de janela e agrupamento baseado no tempo para séries temporais. Ele também suporta junções como as-of, semi e anti. Os Polars podem lidar com dados aninhados com listas e estruturas, remodelar tabelas com pivot e melt e usar expressões poderosas com condições.
Como o Polars se integra ao ecossistema Python?
O Polars funciona bem com outras ferramentas. Você pode facilmente converter dados para pandas, NumPy ou Arrow para machine learning e visualização. Ele suporta formatos de leitura e gravação como CSV, Parquet e IPC. Ele também funciona bem nos notebooks Jupyter e se conecta com várias bibliotecas Python.

