Corso
Se usi regolarmente Python per l’analisi dei dati, come faccio io, ti accorgerai presto che leggere file CSV è uno dei compiti più comuni. Tuttavia, man mano che i tuoi dataset crescono, questo approccio può diventare lento o richiedere molta memoria.
Polars è una libreria DataFrame moderna e veloce per Python, progettata come alternativa ad alte prestazioni a Pandas. Gestisce dataset di grandi dimensioni in modo molto più fluido rispetto agli strumenti tradizionali, perché è costruita con particolare attenzione a velocità e basso consumo di memoria.
La funzione principale di Polars pl.read_csv() offre una soluzione semplice per caricare file CSV in un DataFrame, con opzioni integrate per controllare il parsing, i tipi di dato e l’uso della memoria.
In questa guida ti mostrerò come leggere file CSV, controllare il parsing e gestire dataset di grandi dimensioni usando la funzione pl.read_csv() di Polars. Se stai iniziando ora, dai un’occhiata al nostro corso Introduction to Polars per imparare a manipolare i dati ed estrarre insight con Polars.
Uso di base di pl.read_csv()
Prima di proseguire, consulta il nostro tutorial Python Polars per impostare l’ambiente.
Ora vediamo come funziona la funzione pl.read_csv():
# import the module
import polars as pl
# Load CSV into a Polars DataFrame
fuel_data = pl.read_csv("Fuel_Consumption_2000-2022.csv")
# Preview first few rows
print(fuel_data.head())
Nell’esempio sopra, Polars legge il file e lo carica in un DataFrame. La funzione restituisce un Polars DataFrame, una struttura tabellare simile a quella che otterresti in pandas.
Per impostazione predefinita, pl.read_csv():
-
Presume che la prima riga contenga i nomi delle colonne (
has_header=True) -
Rileva automaticamente i tipi di dato delle colonne
-
Usa la virgola (
,) come delimitatore -
Legge l’intero file in memoria
Parametri comuni in pl.read_csv()
Ora che hai visto come pl.read_csv() carica i dati, vediamo come puoi usare i seguenti parametri per personalizzare il modo in cui Polars esegue il parsing.
Percorso del file e sorgente
Polars ti consente di caricare dati da diverse sorgenti. Puoi passare un percorso locale come stringa, un oggetto Pathlib o persino un URL. Ad esempio, il codice seguente legge da web un file csv di grandi dimensioni con il PIL di vari Paesi in diversi anni.
# Reading from a URL
url = "https://raw.githubusercontent.com/datasets/gdp/master/data/gdp.csv"
gdp_data = pl.read_csv(url)
Delimitatori e separatori
Non tutti i file CSV usano la virgola. Puoi usare l’argomento separator per gestire tabulazioni, punti e virgola, pipe o altri caratteri. L’esempio sotto mostra come specificare i separatori quando leggi i file
# Reading a Semicolon-separated file
sales_data = pl.read_csv("2024_sales.csv", separator=";")
# Reading a Tab-separated file (TSV)
orders_data = pl.read_csv("all_orders.tsv", separator="\t")
Gestione dell’intestazione
Come abbiamo visto, Polars presume che la prima riga dei dati contenga i nomi delle colonne. Se il tuo file non ha una riga di intestazione, usa il parametro has_header=False come mostrato sotto. Polars assegnerà automaticamente nomi come column_1, column_2, column_3 e così via.
# Load file without a header
orders_data = pl.read_csv("all_orders.csv", has_header=False)
Puoi anche rinominare le colonne fornendo i nomi specifici. Per esempio:
# Providing specific column names
sales_data = pl.read_csv("sales_April.csv", new_columns=[
"OrderDate", "OrderNumber", "ProductKey", "SalespersonKey", "Salesperson"])
Codifica
File CSV diversi possono usare codifiche di testo differenti. Se incontri caratteri strani o errori, specifica la codifica:
# Load CSV into a Polars DataFrame
fuel_data = pl.read_csv("Fuel_Consumption_2000-2022.csv", encoding="utf8")
Altre opzioni di codifica comuni includono "latin1" e "utf8-lossy", che gestiscono correttamente i caratteri non validi.
Come selezionare le colonne quando leggi un CSV in Polars
Quando lavori con file CSV grandi, spesso non ti servono tutte le colonne. Polars ti permette di caricare solo le colonne necessarie usando il parametro columns.
# Load only specific columns
fuel_data = pl.read_csv("Fuel_Consumption_2000-2022.csv",
columns=["YEAR", "MAKE", "MODEL"]
)
Selezionando le colonne necessarie già in fase di caricamento, riduci l’uso di memoria evitando dati superflui. Questo metodo velocizza anche la lettura del file e migliora le prestazioni complessive della pipeline.
Come gestire i tipi di dato (schema) nei CSV con Polars
Polars è una libreria fortemente tipizzata, il che significa che ogni colonna deve avere un tipo di dato coerente, ad esempio tutti interi o tutte stringhe.
Inferenza automatica dei tipi
Per impostazione predefinita, Polars ispeziona i dati e determina automaticamente i tipi delle colonne. Questo comportamento funziona bene nella maggior parte dei casi ma a volte può interpretare male alcune colonne, ad esempio trattando gli ID come interi invece che come stringhe.
Specificare lo schema manualmente
Quando vuoi coerenza nel tuo DataFrame, è meglio specificare manualmente lo schema dei dati. Questo garantisce uniformità tra più file e ti aiuta a evitare errori legati ai tipi nelle fasi successive.
Nella maggior parte dei casi, usa schema_overrides per specificare il tipo di dato di colonne particolari lasciando che Polars inferisca le restanti
import polars as pl
# Manually overriding specific data types
empl_data = pl.read_csv(
"all_employees.csv",
schema_overrides={
"id": pl.Int64,
"name": pl.String,
"age": pl.Int64,
"salary": pl.Float64
}
)
Oppure usa schema per definire l’intera struttura del DataFrame.
# Manually define the full schema
empl_data = pl.read_csv(
"all_employees.csv",
schema={
"id": pl.Int64,
"name": pl.String,
"age": pl.Int64,
"salary": pl.Float64
}
)
Come gestire i valori mancanti nei CSV con Polars
Per impostazione predefinita, Polars rileva automaticamente questi valori mancanti e li rappresenta come null. A volte i valori mancanti sono rappresentati da stringhe specifiche, come "NA", "N/A" o "missing". Puoi definirle con null_values per trattarle come null.
# Treating "N/A" and "EMPTY" as nulls
survey_data = pl.read_csv(
"survey_results.csv",
null_values=["N/A", "EMPTY", "null"]
)
Gestendo correttamente i valori mancanti, garantisci tipi di dato coerenti ed eviti calcoli errati, riducendo gli errori durante analisi e modellazione.
Lettura di file CSV di grandi dimensioni in Polars
Quando lavori con dataset di grandi dimensioni che superano la RAM disponibile, Polars dà il meglio, perché elabora i dati senza caricare l’intero file in una volta.
Caricamento lazy con scan_csv()
Invece di caricare subito i dati in memoria come read_csv(), Polars offre un’alternativa lazy, scan_csv(), che costruisce un piano di query ottimizzato ed esegue solo le operazioni necessarie.
Nell’esempio sotto, pl.scan_csv esamina il file CSV senza caricarlo, costruisce una query per prendere solo le colonne “YEAR”, “MAKE” e “MODEL” dove il marchio è “ACURA”, quindi esegue quella query. In questo modo verrà caricata in memoria solo la porzione filtrata di dati, non l’intero file.
# Lazily reference the file (no data loaded yet)
fuel_consumption = pl.scan_csv("Fuel_Consumption_2000-2022.csv")
fuel_consumption_filtered = fuel_consumption.select(
["YEAR", "MAKE", "MODEL"]).filter(pl.col("MAKE") == "ACURA")
# Execute the query and load only the required data
fuel_consumption_acura = fuel_consumption_filtered.collect()
Ti consiglio di usare scan_csv() quando:
- Lavori con file grandi che non stanno comodamente in memoria
- Applichi più trasformazioni, come filtri, selezioni e aggregazioni
- Vuoi l’ottimizzazione della query prima dell’esecuzione
Streaming ed efficienza della memoria
Polars consente anche lo streaming, elaborando i dati a blocchi e mantenendo costante il picco di memoria indipendentemente dalla dimensione del file.
Per file CSV di grandi dimensioni, parti da scan_csv() per creare una query lazy. Il file non viene caricato completamente quando chiami scan_csv().
# Read data in chunks
fuel_consumption = pl.scan_csv("Fuel_Consumption_2000-2022.csv",
low_memory=True)
Dato che il metodo sopra usa comunque read_csv, l’approccio migliore è combinare esecuzione lazy e streaming.
Nell’esempio seguente, Polars elabora il file in pipeline, riga per riga a lotti, mantenendo in memoria solo le righe filtrate (dove "CYLINDERS" > 3) in ogni momento.
# Lazily reference the file (no data loaded yet)
fuel_consumption = pl.scan_csv("Fuel_Consumption_2000-2022.csv")
result = fuel_consumption.filter(pl.col("CYLINDERS") > 3)
# Stream execution instead of loading everything at once
fuel_consumption_high = result.collect(engine="streaming")
Vantaggi prestazionali vs. Pandas
Rispetto a pandas, Polars spesso offre prestazioni migliori nella lettura ed elaborazione dei CSV, come vedremo nella prossima sezione.
Polars read_csv vs Pandas read_csv
La tabella seguente riassume le differenze tra Polars e Pandas nella lettura dei csv in Python.
|
Aspetto |
Polars |
Pandas |
|
Velocità |
Più veloce grazie al multithreading e al parsing ottimizzato |
Più lento con file grandi (per lo più single-thread) |
|
Uso di memoria |
Impronta inferiore; supporta lazy + streaming |
Carica l’intero dataset in memoria in modo eager |
|
Sintassi |
|
|
|
Modello di esecuzione |
Supporta esecuzione lazy ( |
Solo esecuzione eager (immediata) |
|
Ottimizzazione |
Ottimizzazione delle query integrata (proiezione, filtro) |
Ottimizzazione automatica limitata |
|
Miglior caso d’uso |
Dataset grandi, workflow critici per le prestazioni |
Dataset piccoli, analisi rapide |
Ti consiglio di leggere il nostro articolo sulle differenze tra Pandas e Polars per capire quale strumento si adatta meglio alle tue esigenze analitiche.
Lettura di CSV da sorgenti diverse
Come abbiamo visto, puoi usare Polars per leggere file csv da sorgenti diverse. Negli esempi sopra ho mostrato come leggere csv da file locali e URL.
Inoltre, Polars può gestire automaticamente file CSV compressi. Ad esempio, il codice seguente legge dati da un file .gzip.
# Read gzip-compressed CSV
census_data = pl.read_csv("2018_census.csv.gz")
Errori comuni e troubleshooting
Anche con un motore ad alte prestazioni come Polars, possono comunque emergere problemi, soprattutto quando si legge un file csv. Ecco alcuni dei problemi più comuni che ho incontrato e come risolverli.
-
Errori di codifica: Potresti vedere un errore come
UnicodeDecodeError, che indica che il file non usa la codifica UTF-8, problema comune con file più vecchi o CSV esportati da alcune versioni di Excel. Per risolvere, imposta la codifica appropriata o usa"utf8-lossy"se il file ha caratteri incoerenti o danneggiati. -
Problemi di delimitatore: Se il tuo DataFrame si carica ma tutti i dati sono schiacciati in una singola colonna, Polars non ha riconosciuto il separatore. Per risolvere, imposta esplicitamente il delimitatore corretto con l’argomento
separator, ad esempio punto e virgola (;), tabulazione (\t) o pipe (|). -
Tipi di dato errati: A volte Polars può inferire in modo errato i tipi delle colonne, ad esempio leggendo ID numerici come stringhe o incontrando errori di parsing. In questi casi, puoi usare
schema_overridesper specificare il tipo di dato per colonne specifiche. Se vuoi definire i tipi per ogni colonna, usaschema. Puoi anche aumentareinfer_schema_length, così Polars esamina più righe prima di inferire lo schema. -
Problemi di memoria con file grandi: Se il processo Python va in crash durante il caricamento di un file grande, significa che hai esaurito la RAM. Per risolvere, passa da
read_csv()ascan_csv()per il caricamento lazy, così da ridurre l’uso di memoria e migliorare le prestazioni. Puoi anche caricare meno colonne del dataset o usare l’esecuzione in streaming per caricare i dati a blocchi.
Conclusione
La funzione read_csv() in Polars è semplice da usare ma abbastanza potente per compiti reali. A mio avviso, Polars ha un vantaggio netto quando si lavora con dataset in crescita.
Come passo successivo, dai un’occhiata al nostro blog sul motore GPU di Polars per saperne di più sulle sue applicazioni. Se vuoi metterti alla prova, il nostro Super Bowl Analytics with Polars code-along ti guida nel risolvere domande analitiche reali, applicare calcoli e utilizzare tecniche di ML di base nell’analisi sportiva.
FAQs
Qual è la differenza tra read_csv() e scan_csv() in Polars?
read_csv() carica i dati in memoria in modo eager, mentre scan_csv() usa esecuzione lazy ed elabora i dati solo quando chiami .collect().
Quando dovrei usare scan_csv() invece di read_csv()?
Usa scan_csv() per dataset grandi o quando concateni trasformazioni, perché ottimizza l’esecuzione e riduce l’uso di memoria.
Polars può leggere solo colonne specifiche da un file CSV?
Sì, usa il parametro columns=[...] in read_csv() oppure seleziona le colonne in una query lazy con scan_csv().
Come gestisco i valori mancanti nei file CSV con Polars?
Polars tratta i valori vuoti come null per impostazione predefinita e puoi definire marcatori di null personalizzati usando null_values=.
Polars supporta file CSV compressi?
Sì, può leggere formati compressi come .gz e .zip senza estrazione manuale.
