Analisi delle serie storiche e previsioni di serie temporali in R con il metodo Holt-Winters

Una serie storica consta dei valori osservati in un insieme di periodi ordinati sequenzialmente. Questo, per chi fa SEO, è già un elemento del massimo interesse.

I dati di traffico del nostro sito web, considerati lungo una sequenza temporale, sono infatti un esempio di serie storica.

L’analisi delle serie storiche è il procedimento con cui si individuano e isolano i fattori legati al tempo che influenzano i valori osservati nelle serie storiche.

Lo scopo dell’analisi di una serie storica può essere di tipo descrittivo oppure inferenziale, includendo in quest’ultimo la previsione dei valori per periodi di tempo futuri, ancora non occorsi (forecasting).


Il metodo classico di analisi delle serie storiche individua quattro influenze, o componenti:

  1. Trend (T) : il movimento generale a lungo termine dei valori (Y) della serie storica, in un periodo di tempo ampio.
  2. Fluttuazioni cicliche (C) : movimenti ricorrenti di lunga durata.
  3. Variazioni stagionali (S) : fluttuazioni dovute al particolare periodo dell’anno, ad esempio la stagione estiva rispetto ai mesi invernali.
  4. Movimenti erratici o irregolari (I) : deviazioni irregolari dalla tendenza, che non possono essere ascritte a influenze cicliche oppure stagionali.

Secondo il modello dell’analisi classica delle serie storiche, il valore della variabile in ogni periodo è determinato dalle influenze delle quattro componenti.

Lo scopo principale dell’analisi classica delle serie temporali è proprio quello di scomporre la serie, per isolare le influenze delle varie componenti che determinano i valori della serie storica.

Le quattro componenti “classiche” e il loro legame

Le quattro componenti posso essere tra loro legate in modo additivo:

Y = T + C + S + I

ovvero in modo moltiplicativo:

Y = T x C x S x I

Ricordo che un modello moltiplicativo può essere trasformato nel modello additivo sfruttando le proprietà dei logaritmi:

log(Y) = log(T) + log(C) + log(S) + log(I)


Un breve ripasso sui logaritmi…

Il logaritmo di un numero n nella base c (con c diverso da 1 e c >0) è l’esponente al quale è necessario elevare la base c per ottenere n.

Dunque, se n = cb allora logc n = b

Proprietà utili dei logaritmi

  • Quando si moltiplicano tra loro dei numeri, il logaritmo del loro prodotto è la somma dei loro logaritmi.
  • Il logaritmo di una frazione è il logaritmo del numeratore meno il logaritmo del denominatore.
  • Il logaritmo di un numero con esponente è il logaritmo moltiplicato per l’esponente del numero.

Se andiamo a rappresentare graficamente una serie temporale, noteremo quasi sempre tutta una serie di piccole variazioni che possono rendere assai arduo l’obiettivo di individuare tendenze importanti e fare previsioni per il futuro. Proprio per approcciare questo problema sono state sviluppate varie tecniche di «lisciamento» (smoothing), che possiamo per semplicità suddividere in due grandi famiglie: le tecniche che si basano su medie mobili e le tecniche esponenziali.

MEDIA MOBILE
Al posto del dato relativo al mese X calcolo la media di un numero n di mesi di cui X è il punto centrale.
La componente casuale, si compensa se mettiamo assieme diversi mesi, la sua media è uguale a 0 per un numero ragionevole di periodi.
La componente stagionale si ripete regolarmente nel corso dell’anno, allora se distribuisco l’effetto stagionale su tutti i 12 mesi, l’effetto scompare.
Con la media mobile ottengo tutte e due gli effetti voluti: compenso la casualità e “distribuisco” la stagionalità.

R, come vedremo a breve, ci fornisce un aiuto fondamentale mettendoci a disposizione tutta una serie di strumenti per effettuare le nostre analisi con la massima praticità.

Possiamo creare facilmente una serie storica in R usando il comando di base ts().

Dal momento che ho intenzione di usare l’analisi delle serie storiche per ricavare la tendenza e fare una previsione, ho bisogno di importare i dati della mia vista Google Analytics in R.

Posso farlo in maniera “automatica”, usando l’utilissima libreria googleAnalyticsR (che magari sarà oggetto di un post successivo più dettagliato) oppure esportando i dati che mi servono via Query Explorer.

Vediamo il primo caso:

# uso la libreria googleAnalyticsR , che ovviamente devo aver 
# correttamente installato
library(googleAnalyticsR)

# setto l'id della mia vista - codice numerico ids che trovo 
# in Analytics o in Query Esplorer:
view_id <- xxxxxxxxxx 

# Autorizzo Google Analytics
ga_auth()

# Recupero i dati che mi servono - le sessioni da inizio 2017 
# a tutto il 2019 - da Google Analytics:
gadata <- google_analytics(view_id, 
          date_range = c("2017-01-01", "2019-12-31"),
          metrics = "sessions", 
          dimensions = c("yearMonth"),
          max = -1)

# E finalmente converto i dati in una serie temporale 
# con cadenza mensile indicando frequency=12:
ga_ts <- ts(gadata$sessions, start = c(2017,01), end = c(2019,12), frequency = 12)

La procedura per ottenere lo stesso risultato partendo da un file tsv è altrettanto semplice.

Per prima cosa vado sull’interfaccia di Query Explorer
e seleziono il mio account e la vista.

Scelgo la data di inizio e quella di fine (nel mio esempio dal primo gennaio 2017 al 31 dicembre 2019), la metrica che mi interessa (ga:sessions), la dimensione (ga:date).
Un clic sul bottone “Run Query” ed avrò a video il risultato, che posso scaricare in locale cliccando su “Download Results as TSV”.

Nel mio esempio salvo il file come nomefile.tsv

Ora apro con un editor di testo il file ed elimino le prime righe con le informazioni generali e in fondo al file il totale generale.

Se voglio, posso rinominare la riga di header, sostituendo “ga:date” con “data” e “ga:sessions” con “sessioni”, per una migliore leggibilità.

Non ci resta che importare il tsv e creare la serie temporale. Questione di due righe:

# Importo un semplicissimo dataset con data e utenti per giorno
 sitomese <- read.csv('c:/percorso/nomefile.tsv', header = TRUE, sep = "\t")
# Converto i dati in una serie temporale
 sitomese_ts <- ts(sitomese$sessioni, start = c(2017,01), end = c(2019,12), frequency = 12)

Ora che ho la mia serie temporale, ho a disposizione una molteplicità di pacchetti R che mi forniscono tutti gli strumenti utili per analisi di qualunque tipo, dalle più elementari a quelle più approfondite.

Usiamo la media mobile per eliminare la stagionalità

Installo il pacchetto forecast per poter usare l’utilissima funzione ma():

library(forecast)
sitomese.filt<-ma(sitomese_ts,order=12)
sitomese.filt

In questo modo si è applicata una media ponderata alla nostra serie temporale, in modo da limitare l’effetto della stagionalità. Posso ora visualizzare la tendenza stimata con il sistema della media mobile:

lines(sitomese.filt,col="red")

Decompongo la serie storica attraverso le medie mobili

Posso sfruttare la funzione decompose() del pacchetto stats per operare una classica decomposizione della mia serie temporale nelle componenti usando il sistema delle medie mobili e rappresentando in un solo chiarissimo grafico il tutto:

sitomese_ts_decom<-decompose(sitomese_ts)
plot(sitomese_ts_decom)

Decompongo la serie con il metodo LOESS

Un’alternativa più raffinata per la decomposizione della serie è quella che usa il metodo loess. Utilizziamo a tale scopo la funzione stl() del pacchetto stats:

sitomese_ts_stl<-stl(sitomese_ts,s.window = "periodic")
sitomese_ts_stl
plot(sitomese_ts_stl)

Livellamento esponenziale con il metodo di Holt-Winters e previsione

Il livellamento esponenziale è un metodo molto diffuso che ci aiuta a descrivere l’andamento di una serie storica e a effettuare previsioni (forecasting). La libreria forecast ci mette a disposizione la funzione HoltWinters() e la libreria highcharter ci consente di rappresentare graficamente la previsione in maniera molto chiara:

Vediamo il tutto in azione nel nostro esempio completo:

# Per prima cosa carico le librerie che mi servono
library(googleAnalyticsR) # per leggere i dati Analytics
library(forecast) # per le previsioni su serie temporali
library(highcharter) # per ottenere il grafico

# qua inserisco il codice ID
# per trovarlo basta loggarsi in Analytics Query Explorer
# https://ga-dev-tools.appspot.com/query-explorer/
# leggere il valore "ids" per la vista che ci interessa
view_id <- xxxxxxxxx

# Autorizzo Google Analytics
ga_auth()

# e poi recupero i dati da Google Analytics
sitomese <- google_analytics_4(view_id, 
            date_range = c("2017-01-01", "2019-12-31"),
            metrics = "sessions", 
            dimensions = c("yearMonth"),
            max = -1)
# nb: la dimensione dei miei dati è annomese

# Ora esprimo i dati come serie temporale
sitomese_ts <- ts(sitomese$sessions, start = c(2017,01), end = c(2019,12), frequency = 12)
 
# Calcolo il livellamento Holt-Winters per i dati
previsione <- HoltWinters(sitomese_ts)

# e finalmente genero una previsione per i prossimi 12 mesi
hchart(forecast(previsione, h = 12))

Il problema dell’autocorrelazione

Quando il termine che rappresenta l’errore di un periodo è correlato positivamente con lo stesso termine del periodo precedente, sorge il problema dell’autocorrelazione (in questo caso, positiva del primo ordine).
L’autocorrelazione è comune nell’analisi delle serie temporali e dà luogo a errori tipici distorti e dunque a test statistii e intervalli di confidenza scorretti.

Per verificare la presenza o meno di autocorrelazione del primo ordine si utilizza comunemente la tavola della statistica di Durbin-Watson, della quale parleremo in un altro post.


Come si vede già da questo semplice articolo, che non ha altra pretese che proporsi come introduzione e stimolo, l’argomento dell’analisi delle serie storiche a fini SEO presenta aspetti rilevanti e merita di far parte del bagaglio culturale di chiunque, per lavoro o per “semplice” passione, voglia “leggere” dati relativi a sequenze temporali.




Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *