Quando un foglio di calcolo diventa troppo lento o le stesse operazioni vanno ripetute ogni mese, pandas è spesso il passo successivo naturale. È una libreria Python per lavorare con dati tabellari: permette di caricare un file, pulirlo, trasformarlo e riassumerlo con poche righe di codice, che si possono rieseguire identiche sul file del mese dopo. Vediamo i passaggi fondamentali su un esempio concreto: un'esportazione delle vendite di un negozio online.
Caricare i dati
Il file vendite.csv contiene le colonne data, codice_ordine, prodotto, categoria, quantita, prezzo, regione.
import pandas as pd
df = pd.read_csv(
"vendite.csv",
sep=";",
decimal=",",
parse_dates=["data"],
dayfirst=True,
dtype={"codice_ordine": str},
)
Il risultato è un DataFrame, l'oggetto centrale di pandas: una tabella con righe e colonne con un nome, simile a un foglio di calcolo. I parametri non sono un dettaglio: indicano il separatore italiano, la virgola decimale, quali colonne sono date e in che ordine sono scritti giorno e mese, e che il codice d'ordine è testo anche se contiene solo cifre.
Guardare i dati prima di usarli
Il primo passo di ogni analisi è capire che cosa si ha davanti:
df.shape # numero di righe e colonne
df.head() # le prime cinque righe
df.dtypes # il tipo di ogni colonna
df.describe() # statistiche di base sulle colonne numeriche
df.isna().sum() # valori mancanti per colonna
Questi cinque comandi rivelano la maggior parte dei problemi. Se prezzo risulta di tipo object invece che numerico, qualche valore non è stato riconosciuto come numero. Se describe() mostra una quantità minima negativa, ci sono resi o errori da capire. Se una colonna ha molti valori mancanti, bisogna decidere come trattarli prima di fare qualunque calcolo.
Pulire
Alcune operazioni frequenti:
# spazi e maiuscole incoerenti
df["regione"] = df["regione"].str.strip().str.title()
# righe completamente duplicate
df = df.drop_duplicates()
# valori non validi
df = df[df["quantita"] > 0]
# nuova colonna calcolata
df["importo"] = df["quantita"] * df["prezzo"]
Ogni operazione restituisce un nuovo risultato, che va riassegnato. È un errore comune scrivere df.drop_duplicates() senza riassegnare e pensare di aver tolto i duplicati.
Le operazioni lavorano su intere colonne alla volta: df["quantita"] * df["prezzo"] moltiplica tutte le righe insieme. Scrivere un ciclo for che scorre le righe una per una funziona, ma è molto più lento e quasi sempre non necessario.
Filtrare
Le righe si selezionano con condizioni tra parentesi quadre:
marzo = df[(df["data"] >= "2025-03-01") & (df["data"] < "2025-04-01")]
nord = df[df["regione"].isin(["Lombardia", "Piemonte", "Veneto"])]
Le condizioni multiple si combinano con & (e) e | (o), e ciascuna va racchiusa tra parentesi. Usare le parole and e or di Python produce un errore.
Raggruppare e riassumere
È l'equivalente di GROUP BY in SQL e delle tabelle pivot nei fogli di calcolo:
per_categoria = (
df.groupby("categoria")
.agg(ordini=("codice_ordine", "nunique"),
pezzi=("quantita", "sum"),
fatturato=("importo", "sum"))
.sort_values("fatturato", ascending=False)
)
Il risultato è una tabella con una riga per categoria: il numero di ordini distinti, i pezzi venduti e il fatturato, ordinata dalla categoria più importante. Contare gli ordini con nunique invece che con count evita di contare più volte lo stesso ordine quando contiene più prodotti.
Per un andamento mensile:
mensile = df.groupby(df["data"].dt.to_period("M"))["importo"].sum()
E per una vera tabella pivot, con le regioni in riga e i mesi in colonna:
pivot = df.pivot_table(index="regione",
columns=df["data"].dt.to_period("M"),
values="importo", aggfunc="sum", fill_value=0)
Unire due tabelle
Se i costi dei prodotti sono in un altro file, si uniscono come con una JOIN:
costi = pd.read_csv("costi.csv", sep=";", decimal=",")
df = df.merge(costi, on="prodotto", how="left", validate="many_to_one")
df["margine"] = df["importo"] - df["quantita"] * df["costo"]
Il parametro validate è un'assicurazione preziosa: se nel file dei costi lo stesso prodotto compare due volte, pandas segnala un errore invece di duplicare silenziosamente le righe delle vendite e gonfiare i totali. Dopo l'unione conviene controllare quanti prodotti non hanno trovato un costo, con df["costo"].isna().sum().
Salvare i risultati
per_categoria.to_csv("riepilogo_categorie.csv", sep=";", decimal=",")
per_categoria.to_excel("riepilogo.xlsx") # richiede la libreria openpyxl
Il vantaggio rispetto al lavoro manuale è che lo script resta: il mese successivo basta sostituire il file di partenza e rieseguirlo, ottenendo gli stessi passaggi applicati nello stesso modo.
In sintesi
read_csvva configurato con separatore, decimali, date e tipi delle colonne di codici.shape,head,dtypes,describeeisnavanno usati prima di ogni analisi.- Le operazioni lavorano su colonne intere e il risultato va riassegnato.
groupby,aggepivot_tableriassumono i dati;nuniqueevita conteggi doppi.- In
mergeil parametrovalidateimpedisce duplicazioni silenziose delle righe.