📘 Pandas – Capire e manipolare i dati in modo semplice
Una guida spiegata, con esempi utili e un tono amichevole.
1. Perché esiste Pandas?
Quando iniziamo a lavorare seriamente con i dati (analisi, grafici, machine learning…) scopriamo una cosa:
In Python la lista da sola non basta.
Le liste sono ottime, i dizionari anche… ma quando i dati diventano tabellari (come un Excel), iniziamo a voler fare operazioni del tipo:
- “Mostrami solo le righe che rispettano una certa condizione”
- “Calcolami la media dei voti per ogni classe”
- “Riordina i dati in base a una colonna”
- “Gestisci i valori mancanti”
- “Convertimi automaticamente le categorie in numeri”
Con le strutture base di Python tutto questo si può fare, certo…
ma richiede molte righe, molta pazienza e parecchi cicli for.
Pandas fa tutto questo in una riga sola e lo fa in modo leggibile.
2. Cos’è un DataFrame e perché è così importante?
Il DataFrame è il cuore di Pandas. È una “super tabella”, pensata per essere:
- facile da leggere (somiglia a un Excel)
- facile da manipolare (usa metodi chiari)
- veloce internamente (è ottimizzato in C)
- flessibile (colonne di tipi diversi, filtri rapidi, raggruppamenti…)
Un DataFrame è come un foglio di calcolo: ha righe (con un indice) e colonne (ognuna con un nome).
Per rendere tutto molto concreto, iniziamo subito con una tabella di esempio.
3. Un esempio concreto: tabella studenti
import pandas as pd
data = {
"Nome": ["Alice", "Bob", "Carlo", "Diana", "Elena"],
"Età": [17, 18, 17, 18, 17],
"Corso": ["Informatica", "Informatica", "Scientifico", "Scientifico", "Informatica"],
"Voto": [88, 92, 75, 85, 90]
}
df = pd.DataFrame(data)
df
Output:
| Nome | Età | Corso | Voto | |
|---|---|---|---|---|
| 0 | Alice | 17 | Informatica | 88 |
| 1 | Bob | 18 | Informatica | 92 |
| 2 | Carlo | 17 | Scientifico | 75 |
| 3 | Diana | 18 | Scientifico | 85 |
| 4 | Elena | 17 | Informatica | 90 |
Vedi come appare subito leggibile?
- ogni colonna ha un nome
- ogni riga ha un indice
- ogni cella è raggiungibile facilmente
4. Come leggere e capire un DataFrame
Prima di manipolare qualsiasi tabella, serve capirla.
Pandas offre alcune funzioni “diagnostiche”, molto utili.
4.1. df.head() – Guarda le prime righe
Serve per una sbirciatina iniziale, come quando apri un file Excel.
df.head()
Utile con dataset grandi (1000+ righe), perché evita di stampare tutto.
4.2. df.info() – Tipo di dati e struttura
df.info()
Questo comando risponde a domande del tipo:
- quante righe ci sono?
- quante colonne?
- di che tipo sono i valori? (numeri, stringhe…)
- ci sono valori mancanti?
È fondamentale prima di fare machine learning: devi sapere com’è formato il dataset.
4.3. df.describe() – Statistiche numeriche veloci
df.describe()
Ti fa vedere:
- media
- deviazione standard
- minimo e massimo
- quartili
È uno dei modi più rapidi per capire “come si distribuiscono” i numeri del dataset.
5. Selezionare e filtrare i dati
(ovvero: come estrarre solo ciò che ci interessa)
Un DataFrame può essere filtrato in vari modi. Vediamoli con esempi reali sulla tabella degli studenti.
5.1. Selezionare una colonna
df_nome = df["Nome"]
Questo restituisce una Serie, cioè una colonna singola.
5.2. Selezionare più colonne
df_nv = df[["Nome", "Voto"]]
Restituisce un DataFrame più piccolo.
5.3. Filtrare righe in base a una condizione
Esempio: studenti con voto ≥ 90
bravissimi = df[df["Voto"] >= 90]
Perché è comodo?
Perché questo tipo di operazione con liste richiederebbe un for, un if e una lista nuova.
Con Pandas basta una riga.
5.4. Filtri multipli
Studentesse/i di Informatica con voto ≥ 85:
bravi_informatica = df[(df["Voto"] >= 85) & (df["Corso"] == "Informatica")]
Il bello è che la sintassi sembra quasi “linguaggio naturale”.
6. Aggiungere, modificare e rimuovere colonne
6.1. Creare una nuova colonna
Esempio: normalizzare il voto su scala 0–1.
df["Voto_norm"] = df["Voto"] / 100
Perché è importante? Molti algoritmi di machine learning funzionano meglio con valori normalizzati (0,1).
6.2. Modificare una colonna esistente
Se voglio aggiungere 2 voti a tutti gli studenti posso semplicemente aggiungere 2 a tutta la colonna voto, faclie no?
df["Voto"] = df["Voto"] + 2
6.3. Eliminare colonne
utilizzo la funzione drop offerta dall’istanza di DataFrame specificando quali colonne eliminare (lista)
df = df.drop(columns=["Voto_norm"])
7. Ordinare e raggruppare
7.1. Ordinare i dati
utilizzo la funzione sort_values offerta dall’istanza di DataFrame specificando in base a quele colonna ordinare e se in modo crescente (ascending=True) o decrescente (ascending=False)
df.sort_values("Voto", ascending=False)
Per capire “chi ha preso il voto più alto”.
7.2. Raggruppamenti – groupby()
Il metodo groupby() è uno degli strumenti più potenti di Pandas perché permette di riorganizzare i dati in gruppi e applicare funzioni di aggregazione per ottenere informazioni sintetiche (proprio come in SQL 😉).
L’idea è semplice:
“Raggruppa le righe che hanno lo stesso valore in una (o più) colonne, e poi calcola qualcosa su ogni gruppo.”
È un po’ come dire: “fammi la media per ogni classe”, “quanti studenti ci sono per ogni età”, “voto massimo in ogni combinazione corso–età”, ecc.
Raggruppare per una singola colonna
Esempio: media dei voti per corso.
df.groupby("Corso")["Voto"].mean()
Output:
| Corso | Voto medio |
|---|---|
| Informatica | 90 |
| Scientifico | 80 |
Funzioni di aggregazione più comuni (e cosa significano)
Una volta creato il gruppo, puoi applicare molte funzioni utili:
| Funzione | Significato |
|---|---|
mean() | media dei valori |
sum() | somma del gruppo |
max() | valore massimo |
min() | valore minimo |
count() | numero di elementi (escludendo NaN) |
size() | numero di righe (inclusi NaN) |
median() | mediana |
std() | deviazione standard |
var() | varianza |
nunique() | quanti valori diversi compaiono (anche su stringhe) |
La sintassi è sempre:
df.groupby("Colonna")["ColonnaNumerica"].funzione()
Esempi veloci:
df.groupby("Corso")["Voto"].max()
df.groupby("Età")["Voto"].count()
df.groupby("Corso")["Voto"].std()
Raggruppare più colonne insieme
groupby() permette anche di raggruppare per due o più colonne, creando gruppi multidimensionali.
Esempio: media dei voti per coppia (Corso, Età).
df.groupby(["Corso", "Età"])["Voto"].mean()
Output:
| Corso | Età | Voto medio |
|---|---|---|
| Informatica | 17 | 89 |
| Informatica | 18 | 92 |
| Scientifico | 17 | 75 |
| Scientifico | 18 | 85 |
Questo è molto utile quando vuoi analizzare differenze tra categorie incrociate: corso × età, classe × sezione, genere × fascia d’età, ecc.
Applicare più aggregazioni in una volta
Pandas permette di applicare più funzioni insieme usando agg().
Esempio:
df.groupby("Corso")["Voto"].agg(["mean", "max", "min", "count"])
Output:
| Corso | mean | max | min | count |
|---|---|---|---|---|
| Informatica | 90 | 92 | 88 | 3 |
| Scientifico | 80 | 85 | 75 | 2 |
Applicare funzioni diverse a colonne diverse
Puoi anche aggregare più colonne in modo indipendente:
df.groupby("Corso").agg({
"Voto": ["mean", "max"],
"Età": "count"
})
groupby()crea gruppi di righe che condividono lo stesso valore in una o più colonne.- su ogni gruppo applichi una funzione, che “riassume” numericamente il gruppo.
- è perfetto per ottenere statistiche, confronti e analisi descrittive.
- è uno degli strumenti più usati per preparare dati al machine learning o alla visualizzazione.
8. Pulizia dei dati – una fase cruciale nel ML
Molti dataset reali sono sporchi:
- valori mancanti
- duplicati
- tipi sbagliati
- categorie inconsistenti
La pulizia dei dati è uno dei passaggi più importanti nel machine learning.
8.1. Trovare valori mancanti
df.isnull().sum()
Ti dice quante celle vuote ci sono in ogni colonna.
8.2. Sostituire i valori mancanti
df.fillna(0)
Sostituisce i valori nulli con il valore 0 (ma potrebbe essere qualsiasi cosa… anche la media)
8.3. Eliminare righe incomplete
In alternativa possiamo semplicemente eliminare (droppare) le righe con almeno un valore nullo
df.dropna()
8.4. Trovare duplicati
df.duplicated().sum()
8.5. Rimuovere duplicati
df.drop_duplicates()
9. Preparare i dati per il Machine Learning
Quando prepariamo un dataset per un modello di ML, dobbiamo:
- trasformare categorie in numeri
- normalizzare i valori
- separare features e target
- dividere in train/test
9.1. Convertire colonne categoriche in numeri
Pandas lo fa automaticamente:
df_encoded = pd.get_dummies(df, columns=["Corso"])
Trasforma:
| Nome | Corso |
|---|---|
| Bob | Informatica |
in:
| Nome | Corso_Informatica | Corso_Scientifico |
|---|
Questo è ciò che serve alla maggior parte dei modelli ML.
Altro esempio
Ho questa tabella con due colonne categoriche (colore e dimensione dove ognuna ha tre valori possibili):
| Index | Color | Size |
|---|---|---|
| 0 | Red | Small |
| 1 | Blue | Large |
| 2 | Green | Medium |
| 3 | Blue | Small |
| 4 | Red | Large |
applico df_encoded = pd.get_dummies(df, columns=["Color","Size"]) e ottengo:
| Index | Color_Blue | Color_Green | Color_Red | Size_Large | Size_Medium | Size_Small |
|---|---|---|---|---|---|---|
| 0 | False | False | True | False | False | True |
| 1 | True | False | False | True | False | False |
| 2 | False | True | False | False | True | False |
| 3 | True | False | False | False | False | True |
| 4 | False | False | True | True | False | False |
9.2. Normalizzare valori numerici
df["Voto_norm"] = (df["Voto"] - df["Voto"].min()) / (df["Voto"].max() - df["Voto"].min())
In questo esempio trasporto tutti i voti in un range che parte da 0 (sottraggo a tutti i voti il voto minimo) e poi divido ogni voto per l’ampiezza dell’intervallo (max-min). In questo otterrò valori compresi in [0,1]
9.3. Separare features e target
X = df[["Età", "Voto"]]
y = df["Corso"]
In questo modo otterrò in X un dataframe con le sole colonne “Età” e “Voto” e in Y un dataframe con la sola colonna “Corso”.
Questo risulterà estremamente utile quando dovremo addestrare un modello di machine learning perché dovremo esplicitare al modello quali sono i valori di partenza (dati in ingresso (X)) e quali sono quelli da predire (output (Y))
10. Ricettario di esempi utili, spiegati
🔹 Studenti di Informatica
df[df["Corso"] == "Informatica"]
Filtriamo la tabella mantenendo solo le righe dove la colonna “Corso” vale “Informatica”.
🔹 Chi ha il voto massimo?
df["Voto"].max()
Selezioniamo la colonna “Voto” e chiediamo il suo valore massimo.
🔹 Media voti per età
df.groupby("Età")["Voto"].mean()
Raggruppiamo per età → per ogni gruppo calcoliamo la media.
🔹 Aggiungere una colonna “Promosso”
df["Promosso"] = df["Voto"] >= 85
Assegno alla nuova colonna “Promosso” l’esito della condizione voto >= 85. Ricordiamoci che questa condizione viene fatta per tutta la tabella contemporaneamente.
Creare colonne target binarie (due valori) è spesso molto utile per “dire” al mostro modello di ML che una specifica feature sappiamo essere utile.
Perchè è così utile?
Noi umani sappiamo che i voti 5, 6 o 7 sono differenti, lo capisce anche il computer. Il computer sa che 5!=6 e 5!=7 e 6!=7.
Noi umani sappiamo anche che eseguire il salto da 5 a 6 è molto più pesante che eseguire il salto tra 6 e 7. In maniera assoluta (6-5 e 7-6) sono lo stesso salto (1) ma contestualizzato nel registro scolastico sappiamo che i voti >= 6 sono positivi (“verdi”) mentre quelli inferiori al 6 sono negativi (“rossi”).
Di conseguenza, se vogliamo che anche i nostri modelli di ML siano al corrente di questa relazione presente nei dati ma “nascosta” o implicita dobbiamo renderla esplicita.
🔹 Ordinare per corso e poi voto
df.sort_values(["Corso", "Voto"], ascending=[True, False])
Prima ordina alfabeticamente per corso, poi decrescente per voto.