Rimodellare i dati con Pandas: pivot, melt e tabelle incrociate

by theArchitect
SHARE
Rimodellare i dati con Pandas: pivot, melt e tabelle incrociate
© Guida-HTML5.it

Introduzione

Quando si lavora con dati reali, spesso il problema non consiste soltanto nel leggere o filtrare un DataFrame, ma nel trasformare la sua struttura per renderla più adatta all’analisi. Un dataset può essere organizzato in formato “largo”, con molte colonne dedicate a categorie diverse, oppure in formato “lungo”, con una riga per ogni osservazione.

Pandas offre diversi strumenti per rimodellare i dati senza dover scrivere complessi cicli manuali. In questo tutorial vedremo come utilizzare principalmente:

  • melt(), per trasformare un DataFrame largo in uno lungo;
  • pivot(), per trasformare dati lunghi in una struttura tabellare larga;
  • pivot_table(), per creare tabelle pivot con aggregazioni;
  • crosstab(), per analizzare la frequenza combinata di due o più variabili.

Queste tecniche sono molto utili nella preparazione di report, nella costruzione di grafici e nell’analisi di dati provenienti da file CSV o database.

Codice completo

import pandas as pd

# Dataset iniziale in formato largo:
# ogni prodotto ha una colonna distinta per ogni trimestre
vendite_larghe = pd.DataFrame({
    "prodotto": ["Laptop", "Mouse", "Tastiera", "Monitor"],
    "categoria": ["Computer", "Accessori", "Accessori", "Computer"],
    "Q1": [120, 450, 300, 90],
    "Q2": [135, 470, 320, 110],
    "Q3": [150, 510, 340, 125],
    "Q4": [180, 560, 390, 140]
})

print("Dati in formato largo:")
print(vendite_larghe)

# Trasformazione in formato lungo
vendite_lunghe = vendite_larghe.melt(
    id_vars=["prodotto", "categoria"],
    var_name="trimestre",
    value_name="quantita"
)

print("nDati in formato lungo:")
print(vendite_lunghe)

# Ricostruzione della tabella originale con pivot()
vendite_ricostruite = vendite_lunghe.pivot(
    index=["prodotto", "categoria"],
    columns="trimestre",
    values="quantita"
).reset_index()

print("nTabella ricostruita:")
print(vendite_ricostruite)

# Dataset con più righe per prodotto e trimestre
ordini = pd.DataFrame({
    "prodotto": [
        "Laptop", "Laptop", "Mouse", "Mouse",
        "Tastiera", "Tastiera", "Monitor", "Monitor"
    ],
    "trimestre": [
        "Q1", "Q1", "Q2", "Q2",
        "Q3", "Q3", "Q4", "Q4"
    ],
    "canale": [
        "Online", "Negozio", "Online", "Negozio",
        "Online", "Negozio", "Online", "Negozio"
    ],
    "quantita": [70, 50, 280, 190, 200, 140, 80, 60]
})

# Tabella pivot con aggregazione
riepilogo = pd.pivot_table(
    ordini,
    index="prodotto",
    columns="trimestre",
    values="quantita",
    aggfunc="sum",
    fill_value=0,
    margins=True,
    margins_name="Totale"
)

print("nRiepilogo delle quantità:")
print(riepilogo)

# Tabella di frequenza tra categoria e canale
frequenze = pd.crosstab(
    index=ordini["prodotto"],
    columns=ordini["canale"],
    margins=True,
    margins_name="Totale"
)

print("nFrequenze per prodotto e canale:")
print(frequenze)

Spiegazione

Dal formato largo al formato lungo con melt()

Nel formato largo, ogni variabile è spesso rappresentata da una colonna separata. Nel nostro esempio, i trimestri Q1, Q2, Q3 e Q4 sono colonne diverse. Questa struttura è leggibile per una persona, ma non sempre è la più comoda per le analisi automatiche.

Il metodo melt() raccoglie più colonne in due nuove colonne:

  • var_name contiene il nome della variabile, in questo caso il trimestre;
  • value_name contiene il valore associato, cioè la quantità venduta.

Il parametro id_vars indica le colonne che devono rimanere invariate. Nel codice, prodotto e categoria identificano ciascuna osservazione e non devono essere trasformate.

Il risultato è una riga per ogni combinazione prodotto-trimestre. Questo formato è particolarmente adatto a librerie di visualizzazione come Seaborn e Matplotlib, oltre che a molte operazioni di aggregazione.

Dal formato lungo al formato largo con pivot()

Il metodo pivot() esegue l’operazione inversa. Utilizza una colonna come indice delle righe, una come intestazione delle colonne e una come contenuto delle celle.

Nel nostro esempio:

  • index identifica le righe con prodotto e categoria;
  • columns trasforma il trimestre in intestazioni;
  • values specifica quali numeri inserire nella tabella.

È importante ricordare che pivot() richiede una combinazione univoca tra indice e colonna. Se esistono più righe per lo stesso prodotto e trimestre, Pandas genera un errore perché non sa quale valore scegliere.

Aggregare con pivot_table()

Quando sono presenti duplicati, si utilizza pivot_table(). Questo metodo permette di indicare una funzione di aggregazione tramite aggfunc. Nell’esempio viene usata la funzione sum, così le quantità relative allo stesso prodotto e trimestre vengono sommate.

Il parametro fill_value=0 sostituisce con zero le combinazioni senza dati. margins=True, invece, aggiunge una riga e una colonna con i totali complessivi. Queste opzioni sono molto utili per produrre report leggibili.

Analizzare le frequenze con crosstab()

crosstab() crea una tabella di contingenza. È utile quando si vuole contare quante osservazioni appartengono a ciascuna combinazione di categorie. Nel codice viene calcolato il numero di ordini per prodotto e canale di vendita.

Per impostazione predefinita, crosstab() conta le occorrenze. Con il parametro values e una funzione di aggregazione è possibile anche sommare o analizzare una colonna numerica.

Best practice

  • Scegli il formato in base all’obiettivo: il formato lungo è spesso migliore per analisi e grafici, mentre quello largo è comodo per report e riepiloghi.
  • Controlla i duplicati prima di usare pivot(): usa duplicated() per verificare se una combinazione di colonne compare più volte.
  • Preferisci pivot_table() quando i dati non sono univoci: puoi scegliere chiaramente come gestire i duplicati con una funzione come sum, mean, min o max.
  • Assegna nomi espliciti alle colonne: nomi come trimestre e quantita rendono il codice più comprensibile di nomi generici come variable e value.
  • Verifica il risultato: dopo una trasformazione, usa head(), shape e info() per controllare struttura e dimensioni del DataFrame.
  • Gestisci gli indici: dopo pivot() può essere presente un indice gerarchico. Usa reset_index() se ti serve tornare a colonne normali.

Riepilogo

Rimodellare un DataFrame è una competenza fondamentale per lavorare efficacemente con Pandas. melt() converte dati larghi in dati lunghi, mentre pivot() ricostruisce una tabella larga quando le combinazioni sono univoche. Se sono presenti duplicati o se è necessaria un’aggregazione, pivot_table() è la scelta più adatta.

crosstab(), infine, permette di ottenere rapidamente tabelle di frequenza tra variabili categoriche. Combinando questi strumenti è possibile preparare dati disordinati per analisi, grafici e report senza ricorrere a elaborazioni manuali complesse.

Approfondisci con risorse ufficiali

SHARE