Pandas è una delle librerie più versatili del mondo Python. Si basa su NumPy e, a sua volta, offre il fondamento per
molti altri ambienti di lavoro.
Il suo funzionamento è imperniato su due strutture dati principali. La prima è il DataFrame, una sorta di tabella, strutturata su colonne dove i dati sono distribuiti per righe.
Interessante notare che sia le colonne sia le righe sono indicizzate al fine di facilitare l'accesso ad esse singolarmente o a gruppi. Lavorare in Pandas significa essenzialmente manipolare dati con
DataFrame e funzionalità ad essi collegate. L'altra struttura dati è la Series che viene utilizzata per rappresentare righe o colonne di un DataFrame.
A questo punto il nostro scopo è iniziare a prendere confidenza con i DataFrame ed imparare a manipolare i dati al loro interno.
Caricamento di un DataFrame
Un DataFrame nasce solitamente dal caricamento di dati da file o dal suo popolamento partendo da strutture dati. Nel primo caso possiamo, tra i vari, accedere a file
CSV e dopo aver importato la libreria:
import pandas as pd
possiamo richiederle il caricamento dei dati specificando se la prima riga siano intestazioni o meno:
pd.read_csv('file_dati.csv', header=None)
In alternativa, un DataFrame può essere creato partendo dai dati. Strutturiamo un dizionario Python dove le chiavi saranno identificativi per le colonne ed i loro valori liste di
dati che dovranno popolare il DataFrame:
dati= {'nome':['Giorgio', 'Simona', 'Alessia', 'Ivan'],
'cognome': ['Rossi', 'Bianchi', 'Gialli', 'Rossi'],
'eta': [25, 22, 21, 34]}
Fin qui abbiamo solo creato una struttura dati Python normalissima ma possiamo trasformarla in una struttura dati Pandas così:
df=pd.DataFrame(dati, columns=['nome','cognome', 'eta'])
Con il primo argomento abbiamo detto che la sorgente del nuovo DataFrame df
sarà dati
e le colonne che lo popoleranno saranno quelle indicate dalle chiavi
specificate con columns=['nome','cognome', 'eta']
(avremmo anche potuto non sceglierle tutte).
Il DataFrame ottenuto conterrà:
nome cognome eta
0 Giorgio Rossi 25
1 Simona Bianchi 22
2 Alessia Gialli 21
3 Ivan Rossi 34
L'esempio è semplice ma ci mette a disposizione una struttura completa per poter operare le prime selezioni sui dati.
Righe e colonne
Si utilizzano le parentesi quadre per estrarre colonne da un DataFrame. Possiamo incappare in due casi. Se indichiamo il nome di una singola colonna tipo df['nome']
otteniamo una
Series. Se tra parentesi quadre indichiamo una lista di colonne come df[['nome','cognome']]
otteniamo un nuovo DataFrame costituito da queste due colonne.
Per quanto riguarda le righe invece in Pandas è indispensabile fare una distinzione. Ognuna di esse è univocamente indicizzata da un'etichetta, visibile al momento della stampa del DataFrame
(le si può notare nell'output precedente). Al contempo una riga può essere richiamata per posizione conteggiandola a partire da zero. A seconda dei casi saremo noi a scegliere quale forma di indicizzazione
utilizzare. Chiariamo il tutto con un esperimento. Dal DataFrame df dichiarato al paragrafo precedente richiediamo la colonna con etichetta 2 usando l'operatore loc
:
In [1]: df.loc[2]
Out[1]:
nome Alessia
cognome Gialli
eta 21
Name: 2, dtype: object
Possiamo usare anche df.iloc[2]
per accedere alla riga in posizione 2 (la terza conteggiando a partire da 0):
In [2]: df.iloc[2]
Out[2]:
nome Alessia
cognome Gialli
eta 21
Name: 2, dtype: object
Gli output ottenuti sono gli stessi ma se procediamo alla cancellazione della riga 1, df=df.drop(1)
, riassegnando il risultato al riferimento df
il DataFrame
diventa così:
nome cognome eta
0 Giorgio Rossi 25
2 Alessia Gialli 21
3 Ivan Rossi 34
Come vediamo non c'è più alcuna riga con etichetta 1 infatti la direttiva df.loc[1]
restituirà un KeyError in quanto il DataFrame non annovera più alcuna "chiave" di valore
1 mentre df.iloc[1]
restituisce:
In [3]: df.iloc[1]
Out[3]:
nome Alessia
cognome Gialli
eta 21
Name: 2, dtype: object
in quanto finchè il DataFrame conta almeno due righe, la riga in posizione 1 esisterà sempre e sarà comunque la seconda.
Filtrare dati
Altra caratteristica che rende Pandas molto versatile è la possibilità di attuare filtri usando esclusivamente le parentesi quadre. Passeremo condizioni di confronto che coinvolgano
campi e valori. Ad esempio, tutte le righe indicanti una persona di massimo 24 anni si possono individuare così:
In [4]: df[df.eta<24]
Out[4]:
nome cognome eta
1 Simona Bianchi 22
2 Alessia Gialli 21
oppure tutte quelle con cognome uguale a "Rossi" sono:
In [5]: df[df.cognome=='Rossi']
Out[5]:
nome cognome eta
0 Giorgio Rossi 25
3 Ivan Rossi 34
Nel caso in cui si dovranno indicare più condizioni legate tra loro da &
(AND logico) o |
(OR logico) si dovranno racchiudere i singoli confronti tra parentesi tonde in modo da
marcare le priorità di calcolo:
In [6]: df[(df.eta<24) & (df.cognome=='Gialli')]
Out[6]:
nome cognome eta
2 Alessia Gialli 21
In ogni caso, indipendentemente dal numero di righe restituite, il risultato di un filtro sarà comunque un DataFrame.