Una introduzione a Jupyter per l’analisi di dati
Siete stufi di usare Calc di Libreoffice o i vari cloni di Excel?
In questo articolo facciamo una breve introduzione all’uso delle librerie python che si usano nell’analisi di dati mostrando come fare interrogazioni su un file di nostro interesse.
Ci sono due strumenti particolarmente potenti che ci permettono di iniziare ad “andare oltre” il foglio di calcolo: la libreria pandas e jupyter notebooks (una sorta di elaboratore di testi che permette di fare calcoli all’interno del documento stesso).
Useremo Visual Studio Code perché integra tutto questo workflow con le sue estensioni (su Ubuntu lo possiamo installare come Snap con sudo snap install –classic code).
Ci posizioniamo in una nuova cartella (con Apri cartella) e creiamo un nuovo file con estensione .ipynb.
All’apertura di questo nuovo file Code ci chiederà di installare le estensioni python e jupyter che si occuperanno anche di scaricare le librerie python richieste (tramite il gestore di pacchetti pip).
Proviamo a giocare con un file interessante, i prezzi dei carburanti che si trovano sul portale open data del Ministero (su questa pagina).
Abbiamo visto che aprendo il nuovo file l’editor si è trasformato in “blocchi” che possiamo aggiungere e riordinare. Questo ci permette di eseguire anche indipendentemente i singoli blocchi senza eseguire tutte le volte tutto il programma, e ci torna utile se vogliamo fare più cose.
Intanto apriamo il terminale in basso dal menu Visualizza -> Terminale. Da questo andiamo ad installare altra roba che ci servirà
pip3 install pylint ipykernel python-snappy fastparquet pyarrow dask openpyxl
Primo esercizio: scarichiamo il file direttamente dal programma! Utilizziamo la libreria requests che permette di fare richieste http e salviamo il risultato in un file all’interno della cartella nella quale stiamo lavorando.
s= requests.get(‘https://www.mise.gov.it/images/exportCSV/prezzo_alle_8.csv’)
open(‘prezzi.csv’, ‘wb’).write(s.content)
A questo punto possiamo leggere il file all’interno di un “dataframe” (una struttura dati che assomiglia al foglio di calcolo a cui siamo abituati)
file=’prezzi.csv’
df = pd.read_csv(file,low_memory=False, skiprows=[0], header=0, sep=’;’)
Abbiamo letto il file e salvato all’interno della variabile df il suo contenuto. I parametri che abbiamo utilizzato istruiscono la funzione a considerare il punto e virgola come separatore dei campi, a saltare la prima riga (se lo apriamo con gedit notiamo che nella prima riga c’è l’ora di estrazione che non ci serve) ed utilizzare la nuova prima riga come intestazione dei campi.
Una cosa che possiamo fare nel caso di lavorazioni su file di grandi dimensioni è convertire il file in un formato binario che ci permetterà di aprirlo più velocemente le prossime volte.
df.to_parquet(‘prezzi.parquet’, engine=’fastparquet’)
Notiamo che nella cartella si è salvato il file ed è circa un terzo del file originale come dimensione.
Nelle letture successive lo apriremo semplicemente con il comando
df = pd.read_parquet(‘prezzi.parquet’, engine=’fastparquet’)
In una nuova cella possiamo ad esempio vedere la struttura del dataframe con quante righe ci sono ed il tipo dei campi
df.info()
Oppure possiamo vedere le prime 5 righe
df.head()
A noi ci interessa fare una ricerca sul distributore più conveniente, però vediamo che qui c’è solo l’identificatore.
Dobbiamo ripetere la prima parte anche per il file dell’anagrafica e ci ritroviamo pertanto con due dataframe:
anagrafica = pd.read_parquet(‘anagrafica.parquet’, engine=’fastparquet’)
Li possiamo unire con la funzione merge (chi conosce SQL penserà alla join delle interrogazioni) sulla colonna idImpianto che è presente in entrambi i file:
merged = pd.merge(prezzi, anagrafica, on = [‘idImpianto’], how = ‘left’)
Adesso cerchiamo tutti i distributori nel mio comune, per fare un filtro le istruzioni sono <variabile del dataframe> e poi tra quadre la condizione del filtro, nel caso sottostante diciamo di cercare nella colonna Comune del dataframe tutte le righe con valore GENOVA; il risultato lo salviamo nella variabile df1 e la mostriamo a video
df1
Qual’è il prezzo migliore per la mia macchina a diesel? Posso filtrare ancora per il tipo di carburante e selezionare quello migliore, ordinando per prezzo ascendente e mostrando i primi 10.
df1[df1[‘descCarburante’] == ‘Gasolio’].sort_values(by=[“prezzo”], ascending=True).head(10)
Noto che il primo prezzo è un po’ strano (troppo basso ed aggiornato più di una settimana fa), quindi metto una condizione in più guardando le date. Ma attensione: quando abbiamo letto il csv dei prezzi, la libreria ha capito che il campo dtComu è un oggetto, ma per noi deve essere una data altrimenti non possiamo giocarci, la possiamo trasformare semplicemente convertendo e sovrascrivendo la stessa colonna
df1[‘dtComu’] = pd.to_datetime(df1[‘dtComu’])
Consideriamo gli ultimi 7 giorni, quindi generiamo la data di 7 giorni fa e la convertiamo nello stesso formato della nostra colonna
lastweek = dt.date.today() – dt.timedelta(days=7)
lastweek = pd.to_datetime(dt.date.today() – dt.timedelta(days=7))
E modifichiamo la selezione di prima inserendo la nuova condizione.
df1[(df1[‘descCarburante’] == ‘Gasolio’) & (df1[‘dtComu’] > lastweek)].sort_values(by=[“prezzo”], ascending=True).head(10)
Vale la pena fare diversi chilometri per risparmiare 1 millesimo al litro? Una domanda alla quale si può rispondere sia con il buonsenso sia con Python, sta a noi decidere.
Adesso che abbiamo fatto la nostra prima ricerca possiamo allargarci con la documentazione di pandas e con altre librerie che ci permettono ad esempio di fare grafici.