Vai al contenuto principale

Tutorial su Python Polars: guida completa per principianti

Impara a usare Polars in Python con questo tutorial per principianti.
Aggiornato 3 giu 2026  · 11 min leggi

Nel mondo dell’analisi dei dati, pandas è da tempo la scelta predefinita dei professionisti dei dati per gestire i dati tabellari in Python. 

Tuttavia, man mano che i dataset crescono in dimensioni e complessità, pandas può incontrare colli di bottiglia nelle prestazioni, uso limitato del multi-core e vincoli di memoria.

Qui entra in gioco Polars come alternativa moderna. Polars è una libreria DataFrame scritta in Rust che offre prestazioni fulminee, gestione efficiente della memoria e una filosofia di design focalizzata sulla scalabilità.

In questo tutorial, vedremo cos’è Polars e come eseguire alcune operazioni di base con Polars in Python. Se cerchi un’esperienza pratica, ti consiglio di dare un’occhiata al corso Introduction to Polars.

Caratteristiche chiave di Python Polars

python polars

Polars offre un set di funzionalità uniche che lo distinguono da pandas:

  • Fondamenta in Rust: sicurezza e prestazioni a livello di sistema.
  • Esecuzione multi-thread: sfrutta appieno le CPU moderne.
  • Valutazione lazy: rimanda l’esecuzione finché non è esplicitamente richiesta.
  • Applicazione dello schema: garantisce una gestione coerente dei dati.
  • Supporto avanzato dei tipi di dato: gestisce nativamente tipi temporali, categorici e annidati.

Tipi di dato in Polars

Polars supporta un’ampia gamma di tipi di dato oltre alle basi:

  • Numerici: Int32, Int64, Float32, Float64.
  • Booleani: valori true/false.
  • Temporali: Date, Datetime, Duration, Time.
  • Categorici: stringhe codificate per un’archiviazione efficiente in memoria.
  • Annidati: tipi List e Struct, utili per dati in stile JSON.

Vantaggi rispetto a pandas

Essendo l’alternativa più nuova e moderna a pandas, Polars offre diversi vantaggi:

  • Esecuzione più veloce su dataset di grandi dimensioni.
  • Maggiore efficienza di memoria.
  • Più adatto a pipeline ETL e ambienti di produzione.
  • Ottimizzazioni integrate come predicate e projection pushdown.

Installazione e configurazione dell’ambiente per Python Polars

Vediamo ora come iniziare a usare Polars in Python.

Prima di usare Polars, devi configurare correttamente l’ambiente.

Piattaforme supportate

Polars supporta Windows, macOS e Linux. Può essere installato in ambienti virtuali, nel Python di sistema o tramite workflow containerizzati (Docker).

Installazione con pip

Per installare la libreria polars in Python, esegui il seguente comando nel terminale.

pip install polars

Dovresti vedere il seguente messaggio di installazione:

installation message

Installazione con conda

In alternativa, puoi installare la libreria nell’ambiente conda se è quello con cui stai lavorando.

conda install -c conda-forge polars

Verifica dell’installazione

Per verificare che l’installazione sia andata a buon fine, scrivi il seguente semplice script:

import polars as pl
print(pl.__version__)

Configurazione e variabili d’ambiente

Polars ti permette di ottimizzare come viene eseguito e come visualizza gli output impostando variabili d’ambiente prima di avviare la sessione Python. Per esempio:

  • POLARS_MAX_THREADS: limita il numero di thread.
  • POLARS_FMT_MAX_COLS: controlla il numero di colonne stampate.
  • POLARS_FMT_TABLE_WIDTH: regola la larghezza di visualizzazione dei DataFrame.

Ecco un esempio di come imposteresti queste variabili in una shell prima di eseguire Python:

export POLARS_MAX_THREADS=8
export POLARS_FMT_MAX_COLS=20

Generare un dataset CSV di esempio per la dimostrazione

Prima di approfondire le funzionalità di Polars, è utile avere un dataset da usare in modo coerente per tutto il tutorial. Possiamo generare un semplice file CSV usando il modulo csv integrato di Python o pandas. 

Ecco un esempio che crea un file transactions.csv con dati sintetici:

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)

Questo script crea un dataset di 100 transazioni con importi, ID cliente e date di transazione casuali. Puoi adattare intervalli e dimensioni in base alle tue esigenze. 

Salva questo script, eseguilo una volta e avrai un file CSV da usare negli esempi in tutto l’articolo.

Concetti di base in Python Polars: DataFrame e Series

Polars si basa su due astrazioni principali: Series e DataFrame. 

Insieme forniscono un modo strutturato ed efficiente di lavorare con i dati, simile nello spirito a pandas, ma ottimizzato con il backend in Rust di Polars. Vediamo i concetti principali.

Series: array 1D con un tipo definito

Una Series in Polars è un array monodimensionale, simile a una colonna in un foglio di calcolo o in una tabella di database. Ogni Series ha:

  • Un nome (l’etichetta della colonna).
  • Un tipo di dato (come Int64, Utf8, Float64, Boolean, ecc.).
  • Una collezione ordinata di valori.

Poiché il tipo di dato è applicato in modo rigoroso, le Series in Polars tendono a essere più veloci e prevedibili delle liste Python.

Esempio:

import polars as pl
# Create a Series of integers
s = pl.Series("numbers", [1, 2, 3, 4, 5])
print(s)

Output:

shape: (5,)
Series: 'numbers' [i64]
[
    1
    2
    3
    4
    5
]

DataFrame: una collezione di Series

Un DataFrame è una struttura bidimensionale che organizza più Series sotto uno schema. Concettualmente, è come una tabella in SQL o Excel. Le righe rappresentano i record e le colonne rappresentano i campi.

Esempio:

df = pl.DataFrame({
    "id": [1, 2, 3],
    "name": ["Alice", "Bob", "Charlie"],
    "age": [25, 30, 35]
})
print(df)

Output:

shape: (3, 3)
┌─────┬─────────┬─────┐
│ id  │ name    │ age │
│ --- │ ---     │ --- │
│ i64 │ str     │ i64 │
├─────┼─────────┼─────┤
│ 1   │ Alice   │ 25  │
│ 2   │ Bob     │ 30  │
│ 3   │ Charlie │ 35  │
└─────┴─────────┴─────┘

Ogni colonna è una Series e il DataFrame applica il suo schema.

Ruolo degli schemi e coerenza rigorosa dei tipi

Uno dei punti di forza di Polars è l’applicazione rigorosa dello schema. Ogni colonna ha un tipo di dato fisso e Polars garantisce che tutte le operazioni lo rispettino. Questo evita bug sottili che emergono con operazioni a tipizzazione dinamica.

Per esempio, non puoi sommare per errore una colonna di stringhe a una colonna di interi senza una conversione esplicita.

Esempio:

df = df.with_columns(
    (pl.col("age") + 5).alias("age_plus_5")
)
print(df)

Qui, age è i64 e il risultato resta un intero. Se provassi ad aggiungere una colonna di stringhe, Polars solleverebbe un errore invece di fallire in silenzio.

Gestione dei null

I dati reali spesso hanno valori mancanti e Polars offre strumenti chiari per gestirli:

  • fill_null(): sostituisce i null con un valore dato.
  • drop_nulls(): rimuove le righe contenenti null.
  • is_null() / is_not_null(): controlli booleani.

Espressioni: operazioni vettorializzate sulle colonne

Polars promuove un sistema di espressioni, in cui le operazioni sono definite come trasformazioni su colonne anziché cicli Python riga per riga. 

Queste espressioni sono vettorializzate, cioè operano su intere colonne in una volta sola, risultando molto più veloci.

Invece di ciclare manualmente, Polars costruisce un’elaborazione vettoriale veloce.

Esecuzione eager vs lazy

Polars offre due modalità di esecuzione:

1. Esecuzione eager

  • Esegue i calcoli immediatamente.
  • Simile a pandas.
  • Ottima per esplorazione interattiva e dataset piccoli/medi.

Ecco un esempio di esecuzione eager:

df = pl.DataFrame({"x": [1, 2, 3]})
print(df.select(pl.col("x") * 2))  # eager: runs instantly

2. Esecuzione lazy

  • Costruisce un piano di query invece di eseguire subito.
  • Polars ottimizza questo piano sotto il cofano (predicate pushdown, parallelizzazione, projection pruning).
  • Ideale per dataset grandi e trasformazioni complesse.

Ecco un esempio di esecuzione lazy:

lazy_df = pl.DataFrame({"x": [1, 2, 3]}).lazy()
result = lazy_df.select(pl.col("x") * 2).collect()  # execute on collect()
print(result)

Qui non viene calcolato nulla finché non si chiama .collect(). Nei workflow di grandi dimensioni, questo può portare a notevoli miglioramenti di prestazioni.

Operazioni di base sui DataFrame in Python Polars

Ora vedremo come eseguire alcune operazioni di base usate in Polars sul dataset che abbiamo creato.

Caricamento del dataset

Polars può acquisire dati da più formati di file e oggetti in memoria. Questo lo rende flessibile da integrare nelle pipeline dati moderne.

Ecco come puoi farlo per diverse fonti:

Dal dataset CSV che abbiamo creato prima:

import polars as pl

df = pl.read_csv("transactions.csv")
print(df.head())

Possiamo anche leggere il dataset da Parquet se necessario.

df_parquet = pl.read_parquet("transactions.parquet")

Se invece hai un file JSON, puoi leggerlo con questo codice:

df_json = pl.read_json("transactions.json")
#For JSON Lines (NDJSON), use the following instead:
df_json = pl.read_ndjson("transactions.json")

Ecco come leggere dataset da una Arrow Table:

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)

Selezione e filtro

Ora selezioniamo colonne o righe specifiche dal nostro dataset.

Selezionare colonne

Con Polars, un’operazione comune è selezionare le colonne su cui vuoi lavorare e mantenere.

Ecco come puoi farlo:

# Select only transaction_id and amount
df.select(["transaction_id", "amount"])

Filtrare le righe

Puoi anche filtrare le righe in base a condizioni che imposti, in modo simile a pandas.

# Get only high-value transactions above $1,000
high_value = df.filter(pl.col("amount") > 1000)
print(high_value)

Applicare espressioni

Applicare espressioni in Polars significa usare l’oggetto polars.Expr in vari contesti per eseguire trasformazioni sui dati.

Puoi crearle usando pl.col() o 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")
])

Aggregazioni

Possiamo analizzare i modelli di spesa per cliente usando 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)

Output di esempio:

shape: (10, 3)
┌─────────────┬────────────┬───────────────┐
│ customer_id │ total_spent│ avg_transaction│
│ ---         │ ---        │ ---           │
│ i64         │ f64        │ f64           │
├─────────────┼────────────┼───────────────┤
│ 1           │ 5230.12    │ 523.01        │
│ 2           │ 6120.45    │ 680.05        │
│ ...         │ ...        │ ...           │
└─────────────┴────────────┴───────────────┘

Gestione dei valori mancanti

Il nostro dataset generato non ha null di default, ma simuliamo come li gestiremmo.

Riempire i valori mancanti

I valori mancanti possono creare problemi nelle analisi successive e nella visualizzazione dei dati. Dovrai riempire eventuali valori mancanti per assicurare che tutto fili liscio.

Ecco come puoi riempire i valori mancanti:

# Imagine 'amount' has missing values, then replace with 0
df_filled = df.with_columns(
    pl.col("amount").fill_null(0)
)

Eliminare i null

I null possono causare errori se non gestiti. Ecco come eliminarli:

df_no_nulls = df.drop_nulls()

Convertire i tipi

I tipi di dato potrebbero essere formattati in modo errato in un dataset. Ecco come puoi convertirli usando il metodo .cast:

# Ensure customer_id is treated as string instead of int
df_casted = df.with_columns(
    pl.col("customer_id").cast(pl.Utf8)
)

Concatenare operazioni (chaining)

Polars permette il method chaining per workflow più puliti. Questo metodo è comunemente usato in SQL o in R con il pacchetto tidyverse.

Esempio: trova i migliori clienti a marzo per spesa totale

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)

Questa pipeline:

  1. Filtra le transazioni di marzo.
  2. Raggruppa per cliente.
  3. Aggrega la spesa.
  4. Ordina per spesa totale.

Questo metodo di chaining permette di eseguire un’analisi a pipeline senza usare DataFrame intermedi.

Funzionalità avanzate e valutazione lazy in Polars

Oltre alle basi, Polars eccelle con dataset di grandi dimensioni grazie al suo motore di valutazione lazy. Questo modello consente a Polars di costruire prima un piano di query, ottimizzarlo sotto il cofano e solo poi eseguire la pipeline. Il risultato è un enorme aumento di prestazioni ed efficienza, specialmente con milioni di righe o trasformazioni complesse.

Per impostazione predefinita, Polars funziona in modalità eager. Ciò significa che i calcoli avvengono immediatamente, in modo simile a pandas. La modalità lazy, invece, funziona diversamente:

  • Ogni operazione (filter, select, group_by) viene registrata invece di essere eseguita subito.
  • Le trasformazioni vengono eseguite solo quando chiami .collect().
  • Questo rimanda il lavoro finché Polars non può analizzare l’intera pipeline ed eseguirla nel modo più efficiente possibile.

Ecco un esempio in modalità lazy:

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)

Ottimizzazione delle query

Polars ottimizza le query applicando tecniche di pushdown:

  1. Predicate pushdown: i filtri vengono spinti il più vicino possibile alla sorgente dati. Esempio: quando si filtra amount > 1000, Polars applica quel filtro durante la lettura del CSV invece che dopo aver caricato tutte le righe.
  2. Projection pushdown: vengono lette in memoria solo le colonne necessarie. Esempio: se selezioni solo customer_id e amount, Polars evita di leggere completamente transaction_date.

Streaming per grandi moli di dati

Quando i dati sono troppo grandi per entrare in memoria, Polars offre l’esecuzione in streaming. Invece di caricare tutto in una volta, Polars elabora i dati in batch, mantenendo stabile l’uso di memoria.

Questo è particolarmente utile per file CSV o Parquet di molti GB.

Esempio (modalità 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
)

Con streaming=True, Polars evita di costruire enormi tabelle intermedie in memoria, risultando più scalabile di pandas per carichi di lavoro grandi.

Esecuzione con .collect() e debug delle query lazy

Il metodo .collect() è il trigger per eseguire una pipeline lazy. Prima, puoi ispezionare e fare debug del piano di query con:

  • .describe_plan(): mostra il piano logico.
  • .describe_optimized_plan(): mostra il piano ottimizzato dopo che Polars applica pushdown e semplificazioni.

Ottimizzare prestazioni ed efficienza di Python Polars

Polars può aiutarti a migliorare le prestazioni nell’esecuzione delle tue pipeline di analisi.

Ecco alcune best practice:

  • Usa la valutazione lazy per pipeline grandi.
  • Riduci al minimo i cast di tipo.
  • Evita la materializzazione non necessaria di DataFrame intermedi.

Join, merge e combinazione dei dati in Python Polars

Nell’analisi reale spesso serve combinare dataset. Polars offre un set completo di operazioni di join con esecuzione ottimizzata, rendendo semplice unire anche tabelle grandi.

Join supportati

Polars supporta tutti i principali tipi di join:

  • Inner join: mantiene solo le righe corrispondenti.
  • Left / Right join: mantiene tutte le righe di un lato.
  • Outer join: mantiene tutte le righe, riempiendo i mancanti con null.
  • Semi join: mantiene le righe di sinistra che hanno una corrispondenza a destra.
  • Anti join: mantiene le righe di sinistra che non hanno una corrispondenza a destra.
  • Cross join: prodotto cartesiano di entrambe le tabelle.

Esempio: unire le transazioni con i metadati dei clienti

# 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())

Join in Polars vs pandas: prestazioni e usabilità

Polars è superiore a pandas in entrambi gli ambiti:

  • Prestazioni: i join in Polars sono implementati in Rust con parallelismo, risultando più veloci su dataset grandi rispetto a pandas. Predicate e projection pushdown si applicano anche ai join, riducendo movimenti di dati non necessari.
  • Usabilità: Polars richiede chiavi di join esplicite, evitando join accidentali per allineamento degli indici (un’insidia comune in pandas). Semi e anti join sono nativi in Polars, mentre in pandas richiedono workaround.

Funzioni finestra e operazioni rolling in Polars

Le funzioni finestra consentono calcoli all’interno di gruppi o su righe ordinate, senza collassare i risultati, in modo simile alle window function di SQL.

Polars ti permette di calcolare statistiche per cliente o per periodo di tempo usando contesti finestra.

Ecco alcuni esempi di funzioni finestra che puoi usare in Polars:

  • Media/somma rolling per medie mobili.
  • Finestra espandente per statistiche cumulative.
  • Funzioni di ranking per analisi basate sull’ordine.

1. Funzioni running

Esempio: totali progressivi per 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. Funzioni rolling

Le funzioni rolling operano su una finestra scorrevole di righe o tempo.

Esempio: somma rolling su 7 giorni delle transazioni

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())

Finestra espandente (cumulativa) e finestre centrate sono anch’esse supportate regolando i parametri.

3. Funzioni di ranking

Puoi usare funzioni di ranking e aggregazioni personalizzate all’interno di finestre.

Esempio: classifica le transazioni per cliente in base all’importo

ranked = df.with_columns(
    pl.col("amount").rank("dense", descending=True).over("customer_id").alias("rank")
)
print(ranked.head())

Questo produce classifiche (1 = più alto) per la spesa di ciascun cliente.

Le funzioni finestra consentono calcoli contestuali:

print(
    df.group_by("customer_id").agg(pl.col("amount").cum_sum().alias("cumulative_spent"))
)

Usare query SQL in Python Polars

Per gli analisti abituati a SQL, Polars fornisce un contesto SQL per interrogare direttamente i DataFrame con sintassi SQL, sfruttando al contempo la velocità di Polars.

Contesto SQL e registrazione dei DataFrame

Per iniziare, devi registrare un DataFrame prima di eseguire SQL.

from polars import SQLContext

ctx = SQLContext()
ctx.register("transactions", df)

Eseguire query SQL direttamente in Polars

Vediamo un esempio di come eseguire una query SQL in Python usando Polars.

Esempio: query della spesa totale per cliente in 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)

Integrare SQL con le espressioni Polars

Puoi mescolare SQL ed espressioni:

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"))

Questo è utile per team che stanno passando da strumenti basati su SQL.

Integrazione di Python Polars con l’ecosistema più ampio

Polars non è pensato come un’isola a sé stante, ma come una libreria DataFrame ad alte prestazioni che si integra bene con il più ampio ecosistema dei dati in Python. Questa interoperabilità consente ad analisti e ingegneri di adottare Polars in modo graduale continuando a sfruttare gli strumenti esistenti.

Ecco alcune aree di integrazione:

  • Interoperabilità tra pacchetti: conversione fluida tra Polars, pandas, NumPy, Arrow.
  • Visualizzazione: usa matplotlib, seaborn o plotly per i grafici.
  • Machine learning: inserisci i DataFrame Polars in pipeline di scikit-learn, PyTorch o TensorFlow.
  • Cloud e DB: I/O efficiente con Parquet, Arrow e connettori per lo storage cloud.
  • Jupyter notebook: Polars si integra senza problemi in ambienti interattivi.

Esempi e casi d’uso comuni di Python Polars

Infine, diamo un’occhiata rapida ad alcuni esempi di utilizzo di Polars:

1. Pulizia dei dati

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. Pipeline 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. Finanza

Ecco un esempio per le medie mobili degli importi di transazione.

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())

Ecco il risultato atteso:

finance example result

4. Calcolo scientifico

Nel calcolo scientifico, dovrai gestire in modo efficiente milioni di righe di dati sperimentali o simulati simili a transazioni.

Ecco un’implementazione di esempio:

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())

Considerazioni finali

Python Polars offre una libreria DataFrame moderna e ad alte prestazioni che supera molte delle limitazioni di pandas. Sebbene pandas resti popolare per analisi più piccole e ad hoc, Polars è sempre più lo strumento di riferimento per un’elaborazione dati scalabile, efficiente e affidabile in Python.

Vuoi saperne di più su Polars? Ti piaceranno il nostro corso Introduction to Polars o il nostro articolo Introduction to Polars. Potrebbe interessarti anche il nostro articolo sul Polars Engine.

Domande frequenti su Python Polars

Quali sono le principali differenze tra Polars e pandas?

Polars è più veloce e più efficiente in memoria perché è costruito in Rust e usa un motore column-based. Supporta sia la modalità lazy che quella eager, mentre pandas lavora solo in modalità eager. Pandas è più facile per compiti piccoli, ma Polars è migliore per big data e prestazioni.

Come gestisce Polars i dataset di grandi dimensioni rispetto a pandas?

Polars può elaborare file grandi senza caricare tutto in memoria in una volta. Legge solo le colonne e le righe necessarie ed esegue le operazioni in parallelo. Pandas carica l’intero dataset in memoria e di solito lavora su un singolo thread, risultando più lento e pesante.

Puoi spiegare il concetto di valutazione lazy in Polars?

La valutazione lazy significa che prima descrivi cosa vuoi fare e Polars aspetta a eseguire. Quando chiami .collect(), Polars esegue tutti i passaggi insieme in modo ottimizzato. Questo lo rende più veloce perché evita lavoro extra e riduce l’uso di memoria.

Quali sono alcune tecniche avanzate di manipolazione dei dati in Polars?

Polars può eseguire medie mobili, funzioni finestra e raggruppamenti basati sul tempo per le serie temporali. Supporta anche join come as-of, semi e anti join. Polars gestisce dati annidati con liste e struct, ristruttura le tabelle con pivot e melt e usa espressioni potenti con condizioni.

Come si integra Polars con l’ecosistema Python?

Polars funziona bene con altri strumenti. Puoi convertire facilmente i dati in pandas, NumPy o Arrow per machine learning e visualizzazione. Supporta lettura e scrittura di formati come CSV, Parquet e IPC. Funziona senza problemi in Jupyter notebook e si collega a molte librerie Python.

Argomenti

I migliori corsi DataCamp

Programma

Fondamenti di dati in Python

28 h
Accresci le tue competenze sui dati, scopri come manipolarli e visualizzarli e applica analisi avanzate per prendere decisioni basate sui dati.
Vedi dettagliRight Arrow
Inizia il corso
Mostra altroRight Arrow
Correlato

blog

Che cos'è Snowflake? Guida per principianti alla piattaforma dati cloud

Esplora le basi di Snowflake, la piattaforma dati cloud. Scopri la sua architettura, le sue funzionalità e come integrarla nelle tue pipeline di dati.
Tim Lu's photo

Tim Lu

12 min

blog

Tokenizzazione nel NLP: come funziona, sfide e casi d'uso

Guida al preprocessing NLP nel machine learning. Copriamo spaCy, i transformer di Hugging Face e come funziona la tokenizzazione in casi d'uso reali.
Abid Ali Awan's photo

Abid Ali Awan

10 min

blog

I 15 migliori server MCP remoti che ogni AI builder dovrebbe conoscere nel 2026

Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Abid Ali Awan's photo

Abid Ali Awan

15 min

Mostra altroMostra altro