HTML CSS JAVASCRIPT SQL MYSQL PYTHON JAVA PHP C C++ C# PACKET TRACER CYBERSECURITY REACT TYPESCRIPT NODE.JS GIT & GITHUB DATA SCIENCE BOOTSTRAP GO KOTLIN JQUERY DJANGO VUE ANGULAR MONGODB POSTGRESQL SASS NUMPY PANDAS SCIPY DSA RUST SWIFT BASHXMLW3.CSSANGULARJSAIAWSPROGRAMMAZIONEEXCEL WORD POWERPOINT
Corso gratuito

Corso Pandas in italiano

La libreria Python per l'analisi e manipolazione dei dati: Series, DataFrame, lettura CSV/JSON, pulizia dati, GroupBy, merge, correlazioni e grafici. Con esempi pratici ed esercizi.

Pandas — Guida completa in italiano

Pandas è la libreria Python di riferimento per l'analisi e manipolazione dei dati. Costruita sopra NumPy, fornisce due strutture dati potentissime: la Series (1D) e il DataFrame (2D, come un foglio Excel o una tabella SQL).

Il nome deriva da "Panel Data", un termine econometrico per dataset multidimensionali. È lo strumento numero uno per data scientist, analisti e chiunque lavori con dati strutturati in Python.

Cosa puoi fare con Pandas
📥 Leggere/scrivere CSV, Excel, JSON, SQL, Parquet
🧹 Pulire dati: valori mancanti, duplicati, formati errati
🔍 Filtrare, ordinare, raggruppare e aggregare
🔗 Unire (merge/join) più tabelle
📊 Calcolare statistiche e correlazioni
📈 Creare grafici con un solo metodo
💡 Se hai già seguito il corso NumPy, Pandas ti sembrerà familiare: molte operazioni di indicizzazione e filtro funzionano allo stesso modo.

Introduzione a Pandas

Pandas ruota attorno a due strutture dati fondamentali:

StrutturaDimensioniDescrizione
Series1DColonna di dati con un indice etichettato
DataFrame2DTabella: insieme di Series che condividono lo stesso indice
Il tuo primo DataFrame
import pandas as pd

dati = {
    "nome": ["Anna", "Luca", "Marco"],
    "eta": [28, 34, 45],
    "citta": ["Roma", "Milano", "Napoli"]
}

df = pd.DataFrame(dati)
print(df)
#     nome  eta   citta
# 0   Anna   28    Roma
# 1   Luca   34  Milano
# 2  Marco   45  Napoli

print(df.shape)     # (3, 3)
print(df.columns)   # Index(['nome', 'eta', 'citta'], ...)
💡 La convenzione universale è importare Pandas come pd e NumPy come np.

Installazione e importazione

Installazione
# Nel terminale
pip install pandas

# In un notebook Jupyter
!pip install pandas

# Spesso si installano insieme
pip install pandas numpy matplotlib
Importazione e versione
import pandas as pd
import numpy as np

print(pd.__version__)   # es. 2.2.0

# Crea una Series di prova
s = pd.Series([1, 3, 5, 7, 9])
print(s)
🎯 Per lavorare comodamente, usa Jupyter Notebook o Google Colab: i DataFrame vengono visualizzati come tabelle HTML eleganti invece che come testo.

Pandas Series

Una Series è un array 1D etichettato, capace di contenere qualsiasi tipo di dato. Ogni elemento ha un'etichetta (l'indice).

Creare una Series
import pandas as pd

# Da lista — indice automatico 0,1,2...
s = pd.Series([10, 20, 30, 40])
print(s)
# 0    10
# 1    20
# 2    30
# 3    40
# dtype: int64

# Con indice personalizzato
voti = pd.Series([7, 8, 6], index=["mat", "ita", "sci"])
print(voti["ita"])    # 8

# Da dizionario
prezzi = pd.Series({"pane": 1.5, "latte": 1.2, "uova": 2.8})
print(prezzi["latte"]) # 1.2
Operazioni sulle Series
import pandas as pd

s = pd.Series([10, 20, 30, 40, 50])

print(s.sum())    # 150
print(s.mean())   # 30.0
print(s.max())    # 50
print(s * 2)      # raddoppia ogni valore

# Filtro booleano (come in NumPy)
print(s[s > 25])
# 2    30
# 3    40
# 4    50

# Metodi utili
print(s.describe())   # statistiche riassuntive

Pandas DataFrame

Il DataFrame è la struttura più usata: una tabella 2D con righe e colonne etichettate. Puoi pensarla come un dizionario di Series che condividono lo stesso indice.

Creare DataFrame in vari modi
import pandas as pd

# Da dizionario di liste
df = pd.DataFrame({
    "prodotto": ["Mela", "Pane", "Latte"],
    "prezzo": [0.5, 1.2, 1.0],
    "quantita": [100, 50, 80]
})

# Da lista di dizionari
df2 = pd.DataFrame([
    {"nome": "Anna", "eta": 28},
    {"nome": "Luca", "eta": 34}
])

print(df)
Ispezionare un DataFrame
import pandas as pd

df = pd.DataFrame({
    "prodotto": ["Mela", "Pane", "Latte", "Uova"],
    "prezzo": [0.5, 1.2, 1.0, 2.8],
    "quantita": [100, 50, 80, 30]
})

print(df.head(2))      # prime 2 righe
print(df.tail(2))      # ultime 2 righe
print(df.info())       # tipi e memoria
print(df.describe())   # statistiche numeriche
print(df.shape)        # (4, 3)
print(df.dtypes)       # tipo di ogni colonna
Accedere a righe e colonne
import pandas as pd

df = pd.DataFrame({
    "nome": ["Anna", "Luca", "Marco"],
    "eta": [28, 34, 45]
}, index=["a", "b", "c"])

# Una colonna → Series
print(df["nome"])

# Più colonne → DataFrame
print(df[["nome", "eta"]])

# loc: per etichetta
print(df.loc["b"])        # riga con indice "b"
print(df.loc["b", "eta"]) # 34

# iloc: per posizione
print(df.iloc[0])         # prima riga
print(df.iloc[0, 1])      # 28
💡 loc vs iloc: loc usa le etichette dell'indice, iloc usa le posizioni numeriche (come negli array). Ricordare questa differenza evita molti errori.

Leggere file CSV

Il formato CSV (Comma-Separated Values) è il più comune per i dataset. Pandas lo legge con una sola riga.

read_csv e to_csv
import pandas as pd

# Leggere un CSV
df = pd.read_csv("dati.csv")

# Opzioni comuni
df = pd.read_csv(
    "dati.csv",
    sep=";",            # separatore (default ",")
    encoding="utf-8",
    decimal=",",        # virgola decimale (formato IT)
    nrows=1000,         # leggi solo le prime 1000 righe
    usecols=["nome", "prezzo"]  # solo alcune colonne
)

# Salvare un DataFrame come CSV
df.to_csv("output.csv", index=False)
Esplorare un dataset appena letto
import pandas as pd

df = pd.read_csv("vendite.csv")

print(df.head())          # prime 5 righe
print(df.info())          # struttura
print(df.describe())      # statistiche
print(df.columns.tolist())# lista colonne
print(len(df))            # numero righe
print(df["categoria"].unique())   # valori distinti
print(df["categoria"].value_counts())  # conteggi
🎯 pd.read_csv() può leggere anche direttamente da un URL: pd.read_csv("https://.../dati.csv")

Leggere file JSON

Pandas legge anche JSON, formato comune nelle API web. La struttura viene convertita automaticamente in DataFrame.

read_json e to_json
import pandas as pd

# Da file JSON
df = pd.read_json("dati.json")

# Da una stringa JSON
import io
json_str = '''[
    {"nome": "Anna", "eta": 28},
    {"nome": "Luca", "eta": 34}
]'''
df = pd.read_json(io.StringIO(json_str))
print(df)

# Salvare come JSON
df.to_json("output.json", orient="records", indent=2)
JSON annidato con json_normalize
import pandas as pd

dati = [
    {"nome": "Anna", "indirizzo": {"citta": "Roma", "cap": "00100"}},
    {"nome": "Luca", "indirizzo": {"citta": "Milano", "cap": "20100"}}
]

# Appiattisce le strutture annidate
df = pd.json_normalize(dati)
print(df)
#    nome indirizzo.citta indirizzo.cap
# 0  Anna            Roma         00100
# 1  Luca          Milano         20100

Analizzare i dati

Pandas offre metodi rapidi per ottenere una panoramica statistica del tuo dataset.

Metodi di analisi rapida
import pandas as pd

df = pd.DataFrame({
    "venditore": ["Anna", "Luca", "Anna", "Marco", "Luca"],
    "vendite": [250, 180, 320, 150, 290],
    "regione": ["Nord", "Sud", "Nord", "Centro", "Sud"]
})

print(df.describe())           # statistiche numeriche
print(df["vendite"].sum())     # 1190
print(df["vendite"].mean())    # 238.0
print(df["vendite"].median())  # 250.0
print(df["vendite"].std())     # deviazione standard
print(df["venditore"].value_counts())
# Anna     2
# Luca     2
# Marco    1
apply, map e funzioni custom
import pandas as pd

df = pd.DataFrame({
    "nome": ["anna", "luca", "marco"],
    "stipendio": [25000, 32000, 45000]
})

# Applica una funzione a una colonna
df["nome"] = df["nome"].apply(str.capitalize)

# Crea una nuova colonna calcolata
df["stipendio_netto"] = df["stipendio"] * 0.73

# Categorizza con una funzione
def fascia(s):
    if s < 30000: return "Junior"
    elif s < 40000: return "Mid"
    return "Senior"

df["fascia"] = df["stipendio"].apply(fascia)
print(df)

Pulizia dei dati

I dati reali sono sporchi: contengono celle vuote, formati incoerenti, valori errati e duplicati. La pulizia dei dati (data cleaning) è spesso l'80% del lavoro di un data scientist.

ProblemaSoluzione Pandas
Celle vuote (NaN)dropna(), fillna()
Formato sbagliatoto_datetime(), astype()
Dati erratifiltro booleano, replace()
Duplicatidrop_duplicates()
💡 Prima di pulire, esplora sempre con df.info() e df.isnull().sum() per capire dove sono i problemi.

Celle vuote (valori mancanti)

I valori mancanti appaiono come NaN (Not a Number). Hai due strategie: rimuoverli o sostituirli.

Trovare i valori mancanti
import pandas as pd
import numpy as np

df = pd.DataFrame({
    "nome": ["Anna", "Luca", None, "Marco"],
    "eta": [28, np.nan, 45, 33],
    "citta": ["Roma", "Milano", "Napoli", None]
})

print(df.isnull())          # True dove manca
print(df.isnull().sum())    # conteggio per colonna
# nome     1
# eta      1
# citta    1
print(df.isnull().sum().sum())  # 3 totali
Rimuovere vs Riempire
dropna() — rimuove
import pandas as pd
import numpy as np

df = pd.DataFrame({
    "a": [1, 2, np.nan, 4],
    "b": [5, np.nan, 7, 8]
})

# Rimuove righe con almeno un NaN
print(df.dropna())
#      a    b
# 0  1.0  5.0
# 3  4.0  8.0

# Rimuove colonne con NaN
print(df.dropna(axis=1))
fillna() — riempie
import pandas as pd
import numpy as np

df = pd.DataFrame({
    "a": [1, 2, np.nan, 4],
    "b": [5, np.nan, 7, 8]
})

# Riempi con un valore fisso
print(df.fillna(0))

# Riempi con la media della colonna
df["a"] = df["a"].fillna(df["a"].mean())

# Propaga l'ultimo valore valido
print(df.ffill())
🎯 Sostituire i NaN con la media o la mediana è una tecnica comune (imputation). Per dati ordinati nel tempo, ffill()/bfill() sono spesso più sensati.

Formato dei dati sbagliato

Spesso le date sono stringhe e i numeri sono testo. Convertirli al tipo corretto è essenziale per l'analisi.

Convertire le date
import pandas as pd

df = pd.DataFrame({
    "data": ["2024-01-15", "2024/02/20", "15-03-2024"],
    "valore": [100, 200, 300]
})

# Converte stringhe in datetime
df["data"] = pd.to_datetime(df["data"], format="mixed")
print(df["data"].dtype)   # datetime64[ns]

# Ora puoi estrarre componenti
df["anno"] = df["data"].dt.year
df["mese"] = df["data"].dt.month
df["giorno_settimana"] = df["data"].dt.day_name()
print(df)
Convertire i tipi numerici
import pandas as pd

df = pd.DataFrame({
    "prezzo": ["10,50", "20,00", "abc"],
    "qta": ["5", "10", "15"]
})

# Virgola → punto, poi a numero
df["prezzo"] = df["prezzo"].str.replace(",", ".")
# errors="coerce": valori non validi → NaN
df["prezzo"] = pd.to_numeric(df["prezzo"], errors="coerce")

df["qta"] = df["qta"].astype(int)

print(df)
print(df.dtypes)

Dati errati

A volte i dati sono nel formato giusto ma contengono valori impossibili: un'età di 300 anni, un prezzo negativo, un refuso. Vanno corretti o rimossi.

Correggere valori fuori range
import pandas as pd

df = pd.DataFrame({
    "nome": ["Anna", "Luca", "Marco", "Sara"],
    "eta": [28, 350, 45, -5]      # 350 e -5 sono errori
})

# Strategia 1: correggi un valore specifico
df.loc[1, "eta"] = 35

# Strategia 2: imposta limiti sensati
df.loc[df["eta"] > 120, "eta"] = df["eta"].median()
df.loc[df["eta"] < 0, "eta"] = df["eta"].median()

# Strategia 3: rimuovi le righe errate
# df = df[(df["eta"] >= 0) & (df["eta"] <= 120)]

print(df)
replace per correzioni multiple
import pandas as pd

df = pd.DataFrame({
    "citta": ["Roma", "MILANO", "roma", "Napli", "Milano"]
})

# Uniforma maiuscole/minuscole
df["citta"] = df["citta"].str.capitalize()

# Correggi refusi specifici
df["citta"] = df["citta"].replace({"Napli": "Napoli"})

print(df["citta"].value_counts())
# Roma      2
# Milano    2
# Napoli    1

Rimuovere i duplicati

Le righe duplicate falsano le statistiche. Pandas le individua e rimuove facilmente.

Trovare e rimuovere duplicati
import pandas as pd

df = pd.DataFrame({
    "nome": ["Anna", "Luca", "Anna", "Marco", "Luca"],
    "eta": [28, 34, 28, 45, 34]
})

# Quali righe sono duplicate?
print(df.duplicated())
# 0    False
# 1    False
# 2     True   ← duplicato di riga 0
# 3    False
# 4     True   ← duplicato di riga 1

print(df.duplicated().sum())   # 2 duplicati

# Rimuovi i duplicati (tiene la prima occorrenza)
df_pulito = df.drop_duplicates()
print(df_pulito)
Duplicati su colonne specifiche
import pandas as pd

df = pd.DataFrame({
    "email": ["a@x.it", "b@x.it", "a@x.it"],
    "nome": ["Anna", "Bruno", "Anna R."],
    "iscrizione": ["2024-01", "2024-02", "2024-03"]
})

# Duplicati basati solo sull'email
# keep="last" tiene l'ultima occorrenza
df_pulito = df.drop_duplicates(subset="email", keep="last")
print(df_pulito)

# Reset dell'indice dopo la rimozione
df_pulito = df_pulito.reset_index(drop=True)
print(df_pulito)

Selezione e filtro

Selezionare sottoinsiemi di dati è l'operazione più frequente in Pandas. Funziona in modo simile all'indicizzazione booleana di NumPy.

Filtro con condizioni
import pandas as pd

df = pd.DataFrame({
    "nome": ["Anna", "Luca", "Marco", "Sara", "Elena"],
    "eta": [28, 34, 45, 22, 39],
    "citta": ["Roma", "Milano", "Roma", "Napoli", "Milano"],
    "stipendio": [25000, 38000, 52000, 21000, 41000]
})

# Una condizione
print(df[df["eta"] > 30])

# Più condizioni: & (and), | (or), ~ (not)
print(df[(df["eta"] > 30) & (df["stipendio"] > 40000)])

# isin: appartenenza a una lista
print(df[df["citta"].isin(["Roma", "Napoli"])])

# query: sintassi più leggibile
print(df.query("eta > 30 and stipendio > 40000"))
Ordinare i dati
import pandas as pd

df = pd.DataFrame({
    "nome": ["Anna", "Luca", "Marco", "Sara"],
    "eta": [28, 34, 45, 22],
    "stipendio": [25000, 38000, 52000, 21000]
})

# Ordina per una colonna
print(df.sort_values("eta"))

# Decrescente
print(df.sort_values("stipendio", ascending=False))

# Ordina per più colonne
print(df.sort_values(["citta", "eta"]) if "citta" in df else df)

# Top 3 stipendi
print(df.nlargest(3, "stipendio"))
⚠️ Usa & e | (non and/or) per combinare condizioni, e racchiudi ogni condizione tra parentesi: (df["a"] > 1) & (df["b"] < 5).

GroupBy — raggruppare e aggregare

groupby() applica lo schema split-apply-combine: divide i dati in gruppi, applica una funzione a ciascun gruppo, ricombina i risultati. È l'equivalente del GROUP BY di SQL.

GroupBy di base
import pandas as pd

df = pd.DataFrame({
    "regione": ["Nord", "Sud", "Nord", "Sud", "Centro"],
    "venditore": ["Anna", "Luca", "Marco", "Sara", "Elena"],
    "vendite": [250, 180, 320, 150, 290]
})

# Somma vendite per regione
print(df.groupby("regione")["vendite"].sum())
# regione
# Centro    290
# Nord      570
# Sud       330

# Media
print(df.groupby("regione")["vendite"].mean())

# Conteggio
print(df.groupby("regione").size())
Aggregazioni multiple con agg
import pandas as pd

df = pd.DataFrame({
    "categoria": ["A", "B", "A", "B", "A"],
    "vendite": [100, 200, 150, 250, 120],
    "profitto": [20, 50, 30, 60, 25]
})

# Più statistiche in una volta
print(df.groupby("categoria").agg(
    vendite_tot=("vendite", "sum"),
    vendite_media=("vendite", "mean"),
    profitto_max=("profitto", "max"),
    n=("vendite", "count")
))
#            vendite_tot  vendite_media  profitto_max  n
# categoria
# A                  370     123.333333            30  3
# B                  450     225.000000            60  2
💡 GroupBy è uno degli strumenti più potenti di Pandas. Padroneggiarlo ti permette di rispondere a quasi ogni domanda analitica sui tuoi dati.

Merge e Join

Spesso i dati sono divisi in più tabelle. merge() le unisce in base a una colonna comune, esattamente come i JOIN di SQL.

merge tra due DataFrame
import pandas as pd

clienti = pd.DataFrame({
    "id_cliente": [1, 2, 3],
    "nome": ["Anna", "Luca", "Marco"]
})

ordini = pd.DataFrame({
    "id_ordine": [101, 102, 103, 104],
    "id_cliente": [1, 2, 1, 3],
    "totale": [50, 80, 30, 120]
})

# Inner join sulla colonna comune
df = pd.merge(clienti, ordini, on="id_cliente")
print(df)
#    id_cliente   nome  id_ordine  totale
# 0           1   Anna        101      50
# 1           1   Anna        103      30
# 2           2   Luca        102      80
# 3           3  Marco        104     120
Tipi di join e concat
import pandas as pd

a = pd.DataFrame({"k": [1, 2, 3], "x": ["a", "b", "c"]})
b = pd.DataFrame({"k": [2, 3, 4], "y": ["B", "C", "D"]})

# inner (default): solo chiavi comuni
print(pd.merge(a, b, on="k", how="inner"))

# left: tutte le righe di a
print(pd.merge(a, b, on="k", how="left"))

# outer: tutte le righe di entrambi
print(pd.merge(a, b, on="k", how="outer"))

# concat: impila DataFrame
df1 = pd.DataFrame({"x": [1, 2]})
df2 = pd.DataFrame({"x": [3, 4]})
print(pd.concat([df1, df2], ignore_index=True))
howRisultato
innerSolo le chiavi presenti in entrambi
leftTutte le righe di sinistra + match
rightTutte le righe di destra + match
outerTutte le righe di entrambi

Correlazioni

Il metodo corr() calcola la correlazione tra le colonne numeriche: un valore tra -1 e 1 che misura quanto due variabili si muovono insieme.

Matrice di correlazione
import pandas as pd

df = pd.DataFrame({
    "ore_studio": [1, 2, 3, 4, 5, 6, 7],
    "voto": [4, 5, 5, 6, 7, 8, 9],
    "ore_social": [6, 5, 5, 4, 3, 2, 1]
})

# Matrice di correlazione
print(df.corr())
#              ore_studio      voto  ore_social
# ore_studio     1.000000  0.981981   -1.000000
# voto           0.981981  1.000000   -0.981981
# ore_social    -1.000000 -0.981981    1.000000

# Correlazione tra due colonne specifiche
print(df["ore_studio"].corr(df["voto"]))  # 0.98
Valore di corrInterpretazione
vicino a +1Forte correlazione positiva (crescono insieme)
vicino a 0Nessuna correlazione lineare
vicino a -1Forte correlazione negativa (una sale, l'altra scende)
⚠️ Correlazione non implica causalità! Due variabili possono essere correlate per pura coincidenza o per via di un terzo fattore nascosto.

Grafici con Pandas

Pandas integra Matplotlib: ogni DataFrame ha un metodo .plot() per visualizzare i dati con una sola riga.

Grafici di base
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({
    "mese": ["Gen", "Feb", "Mar", "Apr", "Mag"],
    "vendite": [120, 135, 160, 145, 190],
    "costi": [80, 85, 90, 88, 100]
})
df = df.set_index("mese")

# Grafico a linee
df.plot(kind="line", marker="o")
plt.title("Vendite vs Costi")
plt.ylabel("Euro")
plt.savefig("grafico.png")
plt.show()
Tipi di grafico
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({
    "categoria": ["A", "B", "C", "D"],
    "valore": [25, 40, 30, 55]
}).set_index("categoria")

df.plot(kind="bar")       # barre verticali
df.plot(kind="barh")      # barre orizzontali
df.plot(kind="pie", y="valore")  # torta

# Istogramma e scatter (su dati numerici)
serie = pd.Series([1,2,2,3,3,3,4,4,5])
serie.plot(kind="hist", bins=5)

plt.show()
kindTipo di grafico
lineLinee (serie temporali)
bar / barhBarre verticali/orizzontali
histIstogramma (distribuzioni)
scatterDispersione (relazioni)
pieTorta (proporzioni)
boxBox plot (quartili)

Esercizi pratici

🏋️ Esercizio 1 — Analisi vendite

Crea un DataFrame con le vendite di 5 venditori in 3 regioni. Trova: il totale vendite per regione, il venditore con più vendite, e la media vendite generale.

Soluzione Esercizio 1
import pandas as pd

df = pd.DataFrame({
    "venditore": ["Anna","Luca","Marco","Sara","Elena"],
    "regione": ["Nord","Sud","Nord","Centro","Sud"],
    "vendite": [250, 180, 320, 150, 290]
})

# Totale per regione
print(df.groupby("regione")["vendite"].sum())

# Venditore top
top = df.loc[df["vendite"].idxmax()]
print(f"Top: {top['venditore']} con {top['vendite']}")

# Media generale
print(f"Media: {df['vendite'].mean():.1f}")
🏋️ Esercizio 2 — Pulizia dataset

Dato un DataFrame con valori mancanti e duplicati, puliscilo: rimuovi i duplicati, riempi le età mancanti con la media e converti i nomi in formato corretto (prima lettera maiuscola).

Soluzione Esercizio 2
import pandas as pd
import numpy as np

df = pd.DataFrame({
    "nome": ["anna","LUCA","anna","marco"],
    "eta": [28, np.nan, 28, 45]
})

# 1. Rimuovi duplicati
df = df.drop_duplicates()

# 2. Riempi età mancanti con la media
df["eta"] = df["eta"].fillna(df["eta"].mean())

# 3. Formatta i nomi
df["nome"] = df["nome"].str.capitalize()

df = df.reset_index(drop=True)
print(df)
🏋️ Esercizio 3 — Merge e analisi

Hai due tabelle: clienti (id, nome) e ordini (id_cliente, totale). Uniscile e calcola la spesa totale di ogni cliente, ordinando dal più alto.

Soluzione Esercizio 3
import pandas as pd

clienti = pd.DataFrame({
    "id": [1, 2, 3],
    "nome": ["Anna", "Luca", "Marco"]
})
ordini = pd.DataFrame({
    "id_cliente": [1, 2, 1, 3, 2],
    "totale": [50, 80, 30, 120, 45]
})

# Merge
df = pd.merge(clienti, ordini,
              left_on="id", right_on="id_cliente")

# Spesa totale per cliente
spesa = (df.groupby("nome")["totale"].sum()
           .sort_values(ascending=False))
print(spesa)
# nome
# Marco    120
# Luca     125
# Anna      80

E ora?

Complimenti! Hai completato il corso Pandas e ora sai leggere, pulire, analizzare e visualizzare dati reali in Python. Pandas è lo strumento quotidiano di ogni data analyst e data scientist.

Cosa hai imparato:
  • Series e DataFrame: le strutture dati fondamentali
  • Leggere/scrivere CSV e JSON
  • Pulizia dati: valori mancanti, formati, duplicati
  • Selezione, filtro, ordinamento e query
  • GroupBy, merge/join e correlazioni
  • Visualizzazione con .plot()

Il passo successivo? Approfondisci con il corso completo di Data Science, dove userai Pandas insieme a NumPy e Matplotlib su progetti reali.