In questa lezione, affronteremo una serie di funzionalità che è necessario saper utilizzare in Pandas per esplorare e sintetizzare i dati. Gli esempi si rivolgeranno
ad un DataFrame che creeremo direttamente in maniera random qui sfruttando le potenzialità del mondo Python per la generazione di valori casuali.
Il DataFrame di esempio
La generazione dei dati avverrà per colonne utilizzando il costruttore DataFrame
offerto direttamente dal modulo pandas
.
Ecco il codice:
import pandas as pd
from random import choice, randint
def generatore_df(numero_righe=50):
nomi=['Augusto', 'Remo', 'Cesare', 'Maria', 'Fabio', 'Noemi', 'Sara', 'Irene','Alessia']
cognomi=['Rossi', 'Verdi', 'Gialli','Bianchi','Neri','Marroni', 'Arancioni']
citta=['Roma','Milano','Napoli','Venezia','Firenze','Torino','Genova','Bologna']
titolo=['laurea','diploma']
return pd.DataFrame(data={'nome':[choice(nomi) for i in range(0,numero_righe)],
'cognome':[choice(cognomi) for i in range(0,numero_righe)],
'eta':[randint(30,50) for i in range(0, numero_righe)],
'citta':[choice(citta) for i in range(0,numero_righe)],
'titolo':[choice(titolo) for i in range(0,numero_righe)]})
Abbiamo predisposto una funzione di nome generatore_df
in modo da poterla invocare comodamente quando necessario. Di default, genererà
cinquanta righe di dati casuali che descriveranno ipotetiche persone ognuna delle quali contraddistinta da nome, cognome, eta, città di provenienza e
titolo di studio. Per creare un nuovo DataFrame di esempio ci basta invocare la funzione nel seguente modo:
df=generatore_df(100)
e nell'oggetto df
troveremo qualcosa di simile a questo (output prodotto con df.head()
):
nome cognome eta citta titolo
0 Augusto Neri 44 Firenze diploma
1 Irene Gialli 44 Torino laurea
2 Sara Verdi 33 Bologna diploma
3 Remo Rossi 43 Roma diploma
4 Sara Verdi 33 Torino laurea
Iniziamo a questo punto a vedere una serie di funzionalità che ci permettono di conoscere meglio un DataFrame.
Dimensioni e statistiche
Uno dei primi modi per conoscere meglio un DataFrame è quello di prendere confidenza con le sue dimensioni e peculiarità statistiche. La
sua forma ci verrà comunicata velocemente con la proprietà shape
:
In []: df.shape
Out[]: (100, 5)
In []: df.shape[0]
Out[]: 100
In []: df.shape[1]
Out[]: 5
Otteniamo una tupla che ci dirà, in ordine, quante sono le righe e quante le colonne. Trattandosi di tupla, come si vede, ne potremo
estrarre i singoli valori sfruttando gli indici posizionali (0 per le righe e 1 per le colonne). Altri importanti strumenti da padroneggiare saranno
i metodi describe
e info
.
Il primo offre una visione statistica - per lo più a carattere numerico - dei campi presenti nel DataFrame. In uno come il nostro le valutazioni che lo
riguardano potranno essere applicate per lo più al campo eta
essendo l'unico composto da valori numerici. L'effetto di describe
sarà
quello di indicare tutte le principali dimensioni statistiche come media e deviazione standard e tratteggiare confini e distribuzione delle varie grandezze indicando
minimo, massimo e quartili.
In []: df.describe()
Out[]:
eta
count 100.000000
mean 40.420000
std 6.185973
min 30.000000
25% 35.000000
50% 41.000000
75% 45.250000
max 50.000000
Per quanto riguarda info
, questo metodo concede una visione più strutturale sul DataFrame elencando i nomi dei campi e
specificando per ognuno il numero di elementi (con eventuale indicazione di valori nulli) e tipo di dato (pensiamo a object
come generiche stringhe):
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100 entries, 0 to 99
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 nome 100 non-null object
1 cognome 100 non-null object
2 eta 100 non-null int64
3 citta 100 non-null object
4 titolo 100 non-null object
dtypes: int64(1), object(4)
memory usage: 4.0+ KB
Raggruppamenti
Un altro aspetto molto utile per la conoscenza dei DataFrame sono i raggruppamenti, aspetto simile a quanto spesso si fa con le tabelle dei
database (non ci occupiamo qui di selezioni e filtri in quanto già affrontati in una lezione precedente).
In Pandas, si può operare con il metodo groupby
in diversi modi, più o meno sintetici a seconda di cosa stiamo cercando. Qualora ci
interessasse applicare una funzione già presente in Pandas, ad esempio mean
, a seguito di un raggruppamento potremmo utilizzare una
sintassi molto concisa come la seguente:
In []: df.groupby('citta').mean()
Out[]:
eta
citta
Bologna 37.750000
Firenze 42.470588
Genova 38.705882
Milano 39.500000
Napoli 44.600000
Roma 41.444444
Torino 38.833333
Venezia 40.363636
Abbiamo qui chiesto nello specifico di raggruppare dati per città e calcolare la media ove possibile: come in precedenza qui si è proceduto sull'età. Tale operazione
può essere ulteriormente raffinata specificando più campi per il raggruppamento (non solo la città ma anche il titolo di studio) ed indicando esplicitamente
che l'unica grandezza su cui vogliamo il calcolo della media è l'età:
In []: df.groupby(['citta','titolo'])['eta'].mean()
Out[]:
citta titolo
Bologna diploma 40.000000
laurea 35.500000
Firenze diploma 41.750000
laurea 43.111111
Genova diploma 37.714286
laurea 39.400000
Milano diploma 39.000000
laurea 39.727273
Napoli diploma 44.500000
laurea 44.666667
Roma diploma 38.900000
laurea 44.625000
Torino diploma 37.000000
laurea 39.750000
Venezia diploma 37.666667
laurea 43.600000
Name: eta, dtype: float64
Per una maggiore personalizzazione si può poi procedere all'uso del metodo agg
che ci permetterà di indicare quali funzioni vogliamo vengano
applicate ai campi. Nell'esempio che segue calcoleremo la media e la mediana dell'età dopo aver raggruppato per titolo e citta:
In []: df.groupby(['titolo','citta'])['eta'].agg(["mean", "median"])
Out[]:
mean median
titolo citta
diploma Bologna 40.000000 40.0
Firenze 41.750000 42.0
Genova 37.714286 38.0
Milano 39.000000 42.0
Napoli 44.500000 44.5
Roma 38.900000 36.5
Torino 37.000000 37.0
Venezia 37.666667 37.5
laurea Bologna 35.500000 35.5
Firenze 43.111111 43.0
Genova 39.400000 40.5
Milano 39.727273 38.0
Napoli 44.666667 49.0
Roma 44.625000 47.0
Torino 39.750000 40.5
Venezia 43.600000 44.0