2.1 Oggetti tsibble

Una serie storica può essere pensata come una lista di numeri (le misurazioni), cui sono associate informazioni circa gli istanti temporali nei quali quei numeri si sono registrati (l’indice). Questa informazione può essere archiviata come un oggetto tsibble in R.

La variabile indice

Si supponga di avere a disposizione le osservazioni annuali relative agli ultimi anni:

Anno Osservazione
2015 123
2016 39
2017 78
2018 52
2019 110

È possibile trasformare queste informazioni in un oggetto tsibble usando la funzione tsibble():

y <- tsibble(
  Anno = 2015:2019,
  Osservazione = c(123, 39, 78, 52, 110),
  index = Anno
)

Gli oggetti tsibble estendono i dataframe di classe tidy (oggetto tibble) introducendo la struttura temporale. La colonna Anno è stata impostata come indice della serie storica (index), associando le misurazioni (Osservazioni) con l’istante temporale di registrazione (Anno).

Per osservazioni che sono più frequenti di una volta all’anno, è necessario usare una funzione temporale di classe sull’indice. Ad esempio, si supponga di avere un dataset mensile z:

z
#> # A tibble: 5 × 2
#>   Mese     Osservazione
#>   <chr>           <dbl>
#> 1 2019 Jan           50
#> 2 2019 Feb           23
#> 3 2019 Mar           34
#> 4 2019 Apr           30
#> 5 2019 May           25

Questo può essere convertito in un oggetto tsibble utilizzando il codice seguente:

z %>%
  mutate(Mese = yearmonth(Mese)) %>%
  as_tsibble(index = Mese)
#> # A tsibble: 5 x 2 [1M]
#>       Mese Osservazione
#>      <mth>        <dbl>
#> 1 2019 Jan           50
#> 2 2019 Feb           23
#> 3 2019 Mar           34
#> 4 2019 Apr           30
#> 5 2019 May           25

La colonna Mese viene inizialmente convertita da testo ad oggetto temporale mensile con la funzione yearmonth(). Il dataframe viene quindi convertito in un oggetto tsibble identificando la variabile index utilizzando la funzione as_tsibble(). Da notare che l’aggiunta di “[1M]” sulla prima riga indica che si tratta di dati mensili.

Altre funzioni di classe temporale che possono essere utilizzate dipendono dalla frequenza delle osservazioni.

Frequenza Funzione
Annuale start:end
Trimestrale yearquarter()
Mensile yearmonth()
Settimanale yearweek()
Giornaliera as_date(), ymd()
Sotto-giornaliera as_datetime(), ymd_hms()

Le variabili chiave (key)

Un oggetto tsibble permette anche di archiviare serie storiche multiple in un singolo oggetto. Si supponga di essere interessati ad un dataset che contiene i migliori tempi di gara ottenuti nelle gare olimpiche in pista, dai 100m ai 10.000m, femminili e maschili:

olympic_running
#> # A tsibble: 312 x 4 [4Y]
#> # Key:       Length, Sex [14]
#>     Year Length Sex    Time
#>    <int>  <int> <chr> <dbl>
#>  1  1896    100 men    12  
#>  2  1900    100 men    11  
#>  3  1904    100 men    11  
#>  4  1908    100 men    10.8
#>  5  1912    100 men    10.8
#>  6  1916    100 men    NA  
#>  7  1920    100 men    10.8
#>  8  1924    100 men    10.6
#>  9  1928    100 men    10.8
#> 10  1932    100 men    10.3
#> # ℹ 302 more rows

La sintesi sopra mostra che si tratta di un oggetto tsibble, che contiene 312 righe e 4 colonne. La stringa “[4Y]” segnala che l’intervallo di queste osservazioni è quadriennale. A seguire è indicata la struttura della chiave (key), che segnala che nella struttura dati tsibble ci sono 14 serie storiche separate. Viene quindi mostrata un’anteprima delle prime 10 osservazioni, da cui è possibile notare la presenza di un valore mancante nel 1916. Questo perché le Olimpiadi non si sono tenute durante la prima guerra mondiale.

Le 14 serie storiche in questo oggetto sono identificate univocamente dalle chiavi (keys): le variabili Length e Sex. La funzione distinct() può essere utilizzata per mostrare le modalità di ogni variabile o anche di combinazioni di variabili:

olympic_running %>% distinct(Sex)
#> # A tibble: 2 × 1
#>   Sex  
#>   <chr>
#> 1 men  
#> 2 women

Lavorare con oggetti tsibble

È possibile utilizzare le funzioni del package dplyr come mutate(), filter(), select() e summarise() per lavorare con oggetti tsibble. Per mostrare queste funzioni viene ora considerato l’oggetto tibble PBS. Il dataset contiene i dati di vendita sui prodotti farmaceutici in Australia.

PBS
#> # A tsibble: 67,596 x 9 [1M]
#> # Key:       Concession, Type, ATC1, ATC2 [336]
#>       Month Concession   Type    ATC1  ATC1_desc ATC2  ATC2_desc Scripts  Cost
#>       <mth> <chr>        <chr>   <chr> <chr>     <chr> <chr>       <dbl> <dbl>
#>  1 1991 Jul Concessional Co-pay… A     Alimenta… A01   STOMATOL…   18228 67877
#>  2 1991 Aug Concessional Co-pay… A     Alimenta… A01   STOMATOL…   15327 57011
#>  3 1991 Sep Concessional Co-pay… A     Alimenta… A01   STOMATOL…   14775 55020
#>  4 1991 Oct Concessional Co-pay… A     Alimenta… A01   STOMATOL…   15380 57222
#>  5 1991 Nov Concessional Co-pay… A     Alimenta… A01   STOMATOL…   14371 52120
#>  6 1991 Dec Concessional Co-pay… A     Alimenta… A01   STOMATOL…   15028 54299
#>  7 1992 Jan Concessional Co-pay… A     Alimenta… A01   STOMATOL…   11040 39753
#>  8 1992 Feb Concessional Co-pay… A     Alimenta… A01   STOMATOL…   15165 54405
#>  9 1992 Mar Concessional Co-pay… A     Alimenta… A01   STOMATOL…   16898 61108
#> 10 1992 Apr Concessional Co-pay… A     Alimenta… A01   STOMATOL…   18141 65356
#> # ℹ 67,586 more rows

Si tratta di dati mensili sulle prescrizioni Medicare in Australia da luglio 1991 a giugno 2008, classificati secondo i vari tipi di concessione e di indici anatomici terapeutici (ATC - Anatomical Therapeutic Chemical). Ai fini di questo esempio si è interessati alla serie storica Cost (costo totale delle prescrizioni in dollari australiani).

Per estrarre le prescrizioni A10 si può utilizzare la funzione filter():

PBS %>%
  filter(ATC2 == "A10")
#> # A tsibble: 816 x 9 [1M]
#> # Key:       Concession, Type, ATC1, ATC2 [4]
#>       Month Concession   Type   ATC1  ATC1_desc ATC2  ATC2_desc Scripts   Cost
#>       <mth> <chr>        <chr>  <chr> <chr>     <chr> <chr>       <dbl>  <dbl>
#>  1 1991 Jul Concessional Co-pa… A     Alimenta… A10   ANTIDIAB…   89733 2.09e6
#>  2 1991 Aug Concessional Co-pa… A     Alimenta… A10   ANTIDIAB…   77101 1.80e6
#>  3 1991 Sep Concessional Co-pa… A     Alimenta… A10   ANTIDIAB…   76255 1.78e6
#>  4 1991 Oct Concessional Co-pa… A     Alimenta… A10   ANTIDIAB…   78681 1.85e6
#>  5 1991 Nov Concessional Co-pa… A     Alimenta… A10   ANTIDIAB…   70554 1.69e6
#>  6 1991 Dec Concessional Co-pa… A     Alimenta… A10   ANTIDIAB…   75814 1.84e6
#>  7 1992 Jan Concessional Co-pa… A     Alimenta… A10   ANTIDIAB…   64186 1.56e6
#>  8 1992 Feb Concessional Co-pa… A     Alimenta… A10   ANTIDIAB…   75899 1.73e6
#>  9 1992 Mar Concessional Co-pa… A     Alimenta… A10   ANTIDIAB…   89445 2.05e6
#> 10 1992 Apr Concessional Co-pa… A     Alimenta… A10   ANTIDIAB…   97315 2.23e6
#> # ℹ 806 more rows

Questo permette di selezionare le righe dell’oggetto tsibble. È possibile quindi semplificare l’oggetto risultante selezionando le colonne necessarie all’analisi successiva.

PBS %>%
  filter(ATC2 == "A10") %>%
  select(Month, Concession, Type, Cost)
#> # A tsibble: 816 x 4 [1M]
#> # Key:       Concession, Type [4]
#>       Month Concession   Type           Cost
#>       <mth> <chr>        <chr>         <dbl>
#>  1 1991 Jul Concessional Co-payments 2092878
#>  2 1991 Aug Concessional Co-payments 1795733
#>  3 1991 Sep Concessional Co-payments 1777231
#>  4 1991 Oct Concessional Co-payments 1848507
#>  5 1991 Nov Concessional Co-payments 1686458
#>  6 1991 Dec Concessional Co-payments 1843079
#>  7 1992 Jan Concessional Co-payments 1564702
#>  8 1992 Feb Concessional Co-payments 1732508
#>  9 1992 Mar Concessional Co-payments 2046102
#> 10 1992 Apr Concessional Co-payments 2225977
#> # ℹ 806 more rows

La funzione select() consente di selezionare particolari colonne, mentre la funzione filter() consente di mantenere particolari righe.

Si noti che la variabile indice Month, unitamente alle due chiavi Concession e Type, sono conservati, anche se non esplicitamente selezionati, poiché sono richiesti per un oggetto tsibble (per far in modo che ogni riga contenga una combinazione univoca di chiavi ed indice).

Un’altra funzione utile è summarise(), che permette di combinare dati tra le chiavi. Ad esempio, si potrebbe essere interessati a calcolare il costo totale per mese indipendentemente dalle chiavi Concession o Type.

PBS %>%
  filter(ATC2 == "A10") %>%
  select(Month, Concession, Type, Cost) %>%
  summarise(TotalC = sum(Cost))
#> # A tsibble: 204 x 2 [1M]
#>       Month  TotalC
#>       <mth>   <dbl>
#>  1 1991 Jul 3526591
#>  2 1991 Aug 3180891
#>  3 1991 Sep 3252221
#>  4 1991 Oct 3611003
#>  5 1991 Nov 3565869
#>  6 1991 Dec 4306371
#>  7 1992 Jan 5088335
#>  8 1992 Feb 2814520
#>  9 1992 Mar 2985811
#> 10 1992 Apr 3204780
#> # ℹ 194 more rows

La nuova variabile TotalC è la somma di tutti i valori della colonna Cost per ogni mese.

È possibile creare nuove variabili usando la funzione mutate(). Qui ad esempio il totale dei costi viene espresso in milioni di dollari, a partire dai valori in dollari:

PBS %>%
  filter(ATC2 == "A10") %>%
  select(Month, Concession, Type, Cost) %>%
  summarise(TotalC = sum(Cost)) %>%
  mutate(Cost = TotalC/1e6)
#> # A tsibble: 204 x 3 [1M]
#>       Month  TotalC  Cost
#>       <mth>   <dbl> <dbl>
#>  1 1991 Jul 3526591  3.53
#>  2 1991 Aug 3180891  3.18
#>  3 1991 Sep 3252221  3.25
#>  4 1991 Oct 3611003  3.61
#>  5 1991 Nov 3565869  3.57
#>  6 1991 Dec 4306371  4.31
#>  7 1992 Jan 5088335  5.09
#>  8 1992 Feb 2814520  2.81
#>  9 1992 Mar 2985811  2.99
#> 10 1992 Apr 3204780  3.20
#> # ℹ 194 more rows

Infine il tsibble risultante viene salvato nell’oggetto a10 per l’utilizzo in esempi successivi in questo capitolo.

PBS %>%
  filter(ATC2 == "A10") %>%
  select(Month, Concession, Type, Cost) %>%
  summarise(TotalC = sum(Cost)) %>%
  mutate(Cost = TotalC / 1e6) -> a10

In coda a queste serie di funzioni concatenate con l’operatore pipe (%>%) viene utilizzata un’assegnazione destra (->), che non è comune nel codice R, ma è comoda alla fine di una lunga serie di comandi poiché segue il flusso del codice.

Leggere un file csv e convertirlo in un oggetto tsibble

Quasi tutti i dati utilizzati in questo libro sono già archiviati in un oggetto tsibble. La maggior parte dei dati è però memorizzata in database, file MS-Excel o file csv prima di essere importati in R. Il primo passo nella creazione di un tsibble è leggere i dati e identificare quindi le variabili indice e chiave.

Si supponga ad esempio di avere i dati trimestrali archiviati in un file csv (si mostrano di seguito solo le prime 10 righe). Questo dataset contiene informazioni sull’ampiezza della popolazione carceraria in Australia, disaggregata per stato, genere, status legale e stato di origine (qui ATSI sta per Aboriginal - Aborigeni o Torres Strait Islander).

Date State Gender Legal Indigenous Count
2005-03-01 ACT Female Remanded ATSI 0
2005-03-01 ACT Female Remanded Non-ATSI 2
2005-03-01 ACT Female Sentenced ATSI 0
2005-03-01 ACT Female Sentenced Non-ATSI 5
2005-03-01 ACT Male Remanded ATSI 7
2005-03-01 ACT Male Remanded Non-ATSI 58
2005-03-01 ACT Male Sentenced ATSI 5
2005-03-01 ACT Male Sentenced Non-ATSI 101
2005-03-01 NSW Female Remanded ATSI 51
2005-03-01 NSW Female Remanded Non-ATSI 131

È possibile leggere tale file in R e creare un oggetto tsibble semplicemente identificando quale colonna contiene l’indice temporale, e quali sono le colonne chiave. Le restanti colonne contengono valori — possono esserci molte colonne di questo tipo, sebbene in questo esempio ce ne sia una sola (Count). Il file csv originario archivia le date come singoli giorni, sebbene i dati siano in effetti trimestrali, per cui è necessario convertire la variabile Date in trimestri

prison <- readr::read_csv("https://OTexts.com/fpp3/extrafiles/prison_population.csv")
prison <- prison %>%
  mutate(Quarter = yearquarter(Date)) %>%
  select(-Date) %>%
  as_tsibble(key = c(State, Gender, Legal, Indigenous),
             index = Quarter)

prison
#> # A tsibble: 3,072 x 6 [1Q]
#> # Key:       State, Gender, Legal, Indigenous [64]
#>    State Gender Legal    Indigenous Count Quarter
#>    <chr> <chr>  <chr>    <chr>      <dbl>   <qtr>
#>  1 ACT   Female Remanded ATSI           0 2005 Q1
#>  2 ACT   Female Remanded ATSI           1 2005 Q2
#>  3 ACT   Female Remanded ATSI           0 2005 Q3
#>  4 ACT   Female Remanded ATSI           0 2005 Q4
#>  5 ACT   Female Remanded ATSI           1 2006 Q1
#>  6 ACT   Female Remanded ATSI           1 2006 Q2
#>  7 ACT   Female Remanded ATSI           1 2006 Q3
#>  8 ACT   Female Remanded ATSI           0 2006 Q4
#>  9 ACT   Female Remanded ATSI           0 2007 Q1
#> 10 ACT   Female Remanded ATSI           1 2007 Q2
#> # ℹ 3,062 more rows

Questo tsibble contiene 64 serie storiche separate che corrispondono alle combinazioni di 8 stati, 2 generi, 2 status legali e 2 stati di origine. Ognuna di queste serie contiene 48 osservazioni, dal trimestre 2005 Q1 al trimestre 2016 Q4.

Un tsibble, per essere valido, deve contenere un indice univoco per ogni combinazione delle chiavi. In caso contrario, la funzione tsibble() o as_tsibble() segnalerà un errore.

Il periodo stagionale

Alcuni grafici ed alcuni modelli utilizzano il periodo stagionale presente nei dati. Il periodo stagionale è pari al numero di osservazioni prima che il pattern stagionale si ripeta. Nella maggior parte dei casi, questo verrà automaticamente rilevato utilizzando la variabile indicatrice utilizzata per il tempo.

Alcuni periodi comuni per differenti intervalli temporali sono riportati nella tabella seguente:

Dati Minuto Ora Giorno Settimana Anno
Trimestri 4
Mesi 12
Settimane 52
Giorni 7 365.25
Ore 24 168 8766
Minuti 60 1440 10080 525960
Secondi 60 3600 86400 604800 31557600

Per dati trimestrali, mensili e settimanali, c’è solo un periodo stagionale — il numero di osservazioni all’interno di ogni anno. In effetti, non ci sono \(52\) settimane in un anno, ma \(365.25/7 = 52.18\) in media, tenendo conto così di un anno bisestile ogni quattro anni. Approssimare i periodi stagionali ad interi può essere utile in quanto molti termini stagionali nei modelli supportano solo i periodi stagionali interi.

Se i dati sono osservati più di una volta per settimana, allora c’è spesso più di un pattern stagionale nei dati. Ad esempio, dati con osservazioni giornaliere potrebbero avere un pattern stagionale settimanale (periodo \(=7\)) o annuale (periodo \(=365.25\)). Allo stesso modo, dati che sono osservati ogni minuto potrebbero avere stagionalità oraria (periodo\(=60\)), giornaliera (periodo\(=24\times60=1440\)), settimanale (periodo\(=24\times60\times7=10080\)) e annuale (periodo\(=24\times60\times365.25=525960\)).

Pattern stagionali più complicati (ed insoliti) possono essere specificati usando la funzione period() nel package lubridate.