Data Analysis
Dataset con diversi fusi orari
Come gestire il cambio tra ora solare e ora legale in Pandas
This story is also available in English, here
Le date, croce e delizia dell’analisi dati di ogni dataset.
Per lavoro mi occupo spesso di analisi di serie temporali e dati storici.
Uno degli aspetti più critici è il formato con qui le date vengono salvate, soprattutto se si tratta di dati con risoluzione oraria o inferiore: durante il passaggio tra ora solare e ora legale (e viceversa) si creano delle discontinuità che se non trattate possono portare a errori nella gestione dei dati o a errate interpretazioni degli stessi.
In questo articolo vi illustrerò un esempio pratico di questo problema e vi presenterò la soluzione da me trovata.
I DATI
I dati ci erano stati estratti da un database e salvati in formato .csv per essere facilmente analizzati tramite un Jupyter Notebook.
Si presentavano in questo modo:
datetime, variable1, variable2
2020–01–01, 00:00:00+01, 1, 2
2020–01–01, 00:15:00+01, 3, 5
2020–01–01, 00:30:00+01, 7, 9
Era la prima volta che vedevo dati salvati indicando la timezone con “+1” al termine del timestamp, tuttavia ho deciso di provare a lasciar fare il lavoro sporco a Pandas.
my_data = pd.read_csv(filepath,
index_col = ‘datetime’,
parse_dates=True)
my_data.index.dtypeOUTPUT: dtype(‘O’)
Pandas non era riuscito a convertire la colonna datetime in una serie di date e orari! Una rapida ricerca mi ha consentito di spiegare l’arcano: la libreria rilevava la presenza di due fusi orari nella colonna delle date.
Esaminando quindi il dataset in prossimità del cambio d’ora questa era la situazione:
datetime, variable1, variable2
2020–03–29 01:30:00+01, 65, 7
2020–03–29 01:45:00+01, 39, 11
2020–03–29 03:00:00+02, 24, 4
2020–03–29 03:00:15+02, 12, 9
A quanto pare, questa notazione fa sì che Pandas non riesca a interpretare i dati come appartenenti ad un unico fuso orario caratterizzato dal cambio tra ora legale e ora solare, ma li interpreti come due fusi orari distinti!
Che fare ora?
UTC, il fuso orario che piace alle macchine
Dal momento che l’obiettivo era quello di ottenere un formato di data che Pandas riuscisse a manipolare, il primo passo è stato indirizzato dalla libreria stessa: la funzione che trasforma le stringhe in date ha un parametro che permette di convertire automaticamente il risultato nel fuso orario UTC, evitando così qualunque ambiguità dovuta al cambio d’ora.
my_data[‘Datetime’] = pd.to_datetime(
Medium.index,
utc=True,
infer_datetime_format=True)
BINGO! Ero finalmente riuscito ad ottenere le mie date in formato datetime64. Ora potevo finalmente filtrare il mio dataset a piacimento!
Dovevo solo far diventare questa colonna l’indice del mio dataframe:
my_data = my_data.set_index(‘datetime’)
Ma…
Ritorno a casa
Ma mi sono reso presto conto che non potevo fermarmi qui: io volevo filtrare le date utilizzando il mio fuso orario e senza preoccuparmi di dover ogni volta convertire l’input del mio utente in UTC.
Per fortuna, Pandas aveva la funzione giusta anche in questo caso! Convertendo l’indice nel nostro fuso orario potevo finalmente iniziare ad analizzare e visualizzare i dati in modo più facile e intuitivo!
my_data.index = my_data.index.tz_convert(‘Europe/Rome’)
Questo è tutto!
Riassumendo quanto appreso da questa esperienza, quando devo importare delle date in pandas la procedura che seguo è:
- Tentare di importare le date direttamente con pd.read_csv;
se questa procedura fallisce: - Importare le date convertendole in UTC, quindi
- Convertire le date nel fuso orario desiderato
Il bello è che il tutto si può fare in una unica operazione!
my_data.index = my_data.set_index(pd.to_datetime(
my_data.index,
utc=True,
infer_datetime_format=True).tz_convert(‘Europe/Rome’)