pandas offre funzioni di aggregazione pronte all'uso (come sum(), mean(), max()) ma a volte il calcolo che ci serve non esiste tra le opzioni standard.
In questi casi possiamo scrivere la nostra funzione Python e applicarla direttamente al dataframe con agg().
In questa micro-lezione vedremo come fare passo dopo passo.
Il programma della micro-lezione
La libreria e il dataframe
Per prima cosa importiamo le librerie:
import pandas as pd
import numpy as npAdesso creiamo un dataframe di esempio.
Immagina di gestire i dati di un team di vendita: ogni riga è una vendita, con il nome del venditore, la regione e l'importo.
df = pd.DataFrame({
'venditore': ['Anna', 'Anna', 'Anna', 'Marco', 'Marco', 'Giulia', 'Giulia', 'Giulia'],
'regione': ['Nord', 'Nord', 'Sud', 'Nord', 'Sud', 'Sud', 'Sud', 'Nord'],
'importo': [1200, 850, 2100, 3400, 980, 760, 1900, 1100]
})Ecco l’aspetto del nostro dataframe:
venditore | regione | importo |
|---|---|---|
Anna | Nord | 1200 |
Anna | Nord | 850 |
Anna | Sud | 2100 |
Marco | Nord | 3400 |
Marco | Sud | 980 |
Giulia | Sud | 760 |
Giulia | Sud | 1900 |
Giulia | Nord | 1100 |
Come funziona agg()
agg() è il metodo che pandas usa per applicare funzioni di aggregazione a un gruppo di righe.
Di solito lo vedi così:
(df
.groupby('venditore', as_index=False)['importo']
.agg('sum')
)In poche parole, stai dicendo a pandas: prendi la colonna importo, applica la funzione sum e raggruppa per venditore.
Ma al posto di sum puoi usare qualsiasi funzione, compresa una che hai scritto tu.
Se non hai familiarità con groupby(), puoi consultare questa micro-lezione.
Scrivere una funzione di aggregazione personalizzata
Una funzione di aggregazione personalizzata riceve in input una Series e restituisce un singolo valore.
Supponiamo di voler calcolare il range delle vendite per ogni venditore, cioè la differenza tra la vendita più alta e quella più bassa.
Non esiste una funzione standard per questo. Perciò, dobbiamo crearne una:
def range_vendite(s):
return s.max() - s.min()La funzione riceve s, che è una Series e restituisce la differenza tra il valore massimo e il valore minimo minimo.
La funzione di per sé non è legata al nostro dataframe, ma è generica.
Nel prossimo passaggio vedremo come applicarla al nostro dataframe.
Attenzione!
La funzione deve sempre restituire un singolo valore scalare: un numero, una stringa, un booleano.
Se restituisce una lista o una Series, pandas non saprà come gestirla nell'output finale.
Applicarla con groupby() e agg()
Una volta definita la funzione, puoi passarla quando usi agg() come se fosse una funzione normale:
(df
.groupby('venditore', as_index=False)['importo']
.agg(range_vendite)
)Ed ecco qui il risultato:
venditore | importo |
|---|---|
Anna | 1250 |
Giulia | 1140 |
Marco | 2420 |
In questo caso la colonna importo contiene il risultato della nostra funzione di aggregazione personalizzata, ovvero il range delle vendite.
Anna ha vendite tra 850€ e 2100€: il range è 1250€. Marco ha vendite tra 980€ e 3400€: range di 2420€: è il più variabile del team. Giulia è la più costante, con un range di 1140€.
Questo tipo di informazione, la variabilità delle performance, non si ottiene con nessuna delle funzioni standard di pandas.
Usare più aggregazioni insieme
Puoi combinare funzioni standard e funzioni personalizzate in un unico utilizzo di agg(), usando un dizionario.
In questo modo puoi anche dare un nome specifico alle colonne delle aggregazioni.
Ecco come fare:
(df.groupby('venditore', as_index=False)['importo']
.agg(
totale='sum',
media='mean',
variabilità=range_vendite
)
)Ed ecco qui il risultato:
venditore | totale | media | variabilità |
|---|---|---|---|
Anna | 4150 | 1383.3 | 1250 |
Giulia | 3760 | 1253.3 | 1140 |
Marco | 4380 | 2190.0 | 2420 |
Puoi anche scrivere funzioni più elaborate. Per esempio, una che calcola la percentuale di vendite sopra una certa soglia:
def pct_sopra_soglia(s, soglia=1000):
return round((s.gt(soglia).sum() / len(s)) * 100, 1)
Ed ecco come applicarla al dataframe:
(df.
groupby('venditore', as_index=False)['importo']
.agg(
totale='sum',
pct_grandi=pct_sopra_soglia
)Ed ecco qui il risultato:
venditore | totale | pct_grandi |
|---|---|---|
Anna | 4150 | 66.7 |
Giulia | 3760 | 50.0 |
Marco | 4380 | 50.0 |
Anna ha il 66.7% delle sue vendite sopra i 1000€: due su tre. Marco e Giulia sono al 50%.
Conclusione
Le aggregazioni personalizzate sono uno degli strumenti più potenti di pandas proprio perché non ti limitano alle funzioni predefinite.
Basta scrivere una funzione Python che riceve una Series e restituisce un valore e tutto il resto lo gestisce agg().
Con questa tecnica puoi calcolare metriche specifiche o qualsiasi altra statistica che ha senso per il tuo contesto.
Alla prossima micro-lezione 👋
Se vuoi imparare la data analysis con micro-lezioni che vanno dritto al sodo, iscriviti alla newsletter: