Tendenza STL delle serie storiche usando R


27

Sono nuovo di R e dell'analisi delle serie storiche. Sto cercando di trovare la tendenza di lunghe (40 anni) serie temporali giornaliere di temperatura e ho cercato di approssimazioni diverse. Il primo è solo una semplice regressione lineare e il secondo è la decomposizione stagionale delle serie temporali di Loess.

In quest'ultimo sembra che la componente stagionale sia maggiore della tendenza. Ma come posso quantificare la tendenza? Vorrei solo un numero che dicesse quanto è forte quella tendenza.

     Call:  stl(x = tsdata, s.window = "periodic")
     Time.series components:
        seasonal                trend            remainder               
Min.   :-8.482470191   Min.   :20.76670   Min.   :-11.863290365      
1st Qu.:-5.799037090   1st Qu.:22.17939   1st Qu.: -1.661246674 
Median :-0.756729578   Median :22.56694   Median :  0.026579468      
Mean   :-0.005442784   Mean   :22.53063   Mean   : -0.003716813 
3rd Qu.:5.695720249    3rd Qu.:22.91756   3rd Qu.:  1.700826647    
Max.   :9.919315613    Max.   :24.98834   Max.   : 12.305103891   

 IQR:
         STL.seasonal STL.trend STL.remainder data   
         11.4948       0.7382    3.3621       10.8051
       % 106.4          6.8      31.1         100.0  
     Weights: all == 1
     Other components: List of 5   
$ win  : Named num [1:3] 153411 549 365  
$ deg  : Named int [1:3] 0 1 1   
$ jump : Named num [1:3] 15342 55 37  
$ inner: int 2  
$ outer: int 0

inserisci qui la descrizione dell'immagine

Risposte:


20

Non mi preoccuperei stl()per questo: l'ampiezza di banda per gli smorzatori lowess usati per estrarre la tendenza è di gran lunga troppo piccola con conseguente fluttuazioni su piccola scala che vedi. Vorrei usare un modello additivo. Ecco un esempio usando i dati e il codice modello dal libro di Simon Wood su GAM:

require(mgcv)
require(gamair)
data(cairo)
cairo2 <- within(cairo, Date <- as.Date(paste(year, month, day.of.month, 
                                              sep = "-")))
plot(temp ~ Date, data = cairo2, type = "l")

dati di temperatura del Cairo

Adatta un modello con tendenza e componenti stagionali --- attenzione che è lento:

mod <- gamm(temp ~ s(day.of.year, bs = "cc") + s(time, bs = "cr"),
            data = cairo2, method = "REML",
            correlation = corAR1(form = ~ 1 | year),
            knots = list(day.of.year = c(0, 366)))

Il modello montato si presenta così:

> summary(mod$gam)

Family: gaussian 
Link function: identity 

Formula:
temp ~ s(day.of.year, bs = "cc") + s(time, bs = "cr")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  71.6603     0.1523   470.7   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1   1 

Approximate significance of smooth terms:
                 edf Ref.df       F p-value    
s(day.of.year) 7.092  7.092 555.407 < 2e-16 ***
s(time)        1.383  1.383   7.035 0.00345 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1   1 

R-sq.(adj) =  0.848  Scale est. = 16.572    n = 3780

e possiamo visualizzare la tendenza e i termini stagionali tramite

plot(mod$gam, pages = 1)

Il Cairo ha adattato tendenza e stagionale

e se vogliamo tracciare la tendenza sui dati osservati, possiamo farlo con la previsione tramite:

pred <- predict(mod$gam, newdata = cairo2, type = "terms")
ptemp <- attr(pred, "constant") + pred[,2]
plot(temp ~ Date, data = cairo2, type = "l",
     xlab = "year",
     ylab = expression(Temperature ~ (degree*F)))
lines(ptemp ~ Date, data = cairo2, col = "red", lwd = 2)

Tendenza adatta al Cairo

O lo stesso per il modello attuale:

pred2 <- predict(mod$gam, newdata = cairo2)
plot(temp ~ Date, data = cairo2, type = "l",
     xlab = "year",
     ylab = expression(Temperature ~ (degree*F)))
lines(pred2 ~ Date, data = cairo2, col = "red", lwd = 2)

Modello misura Cairo

Questo è solo un esempio e un'analisi più approfondita potrebbe avere a che fare con il fatto che mancano alcuni dati, ma quanto sopra dovrebbe essere un buon punto di partenza.

Quanto al tuo punto su come quantificare la tendenza - beh, questo è un problema, perché la tendenza non è lineare, né nella tua stl()versione né nella versione GAM che mostro. Se lo fosse, potresti dare il tasso di variazione (pendenza). Se vuoi sapere di quanto è cambiata la tendenza stimata durante il periodo di campionamento, allora possiamo usare i dati contenuti prede calcolare la differenza tra l'inizio e la fine della serie solo nel componente tendenza :

> tail(pred[,2], 1) - head(pred[,2], 1)
    3794 
1.756163

quindi le temperature sono, in media, 1,76 gradi più calde rispetto all'inizio del record.


Guardando il grafico, penso che ci possa essere una certa confusione tra Fahrenheit e Celsius.
Henry,

Ben notato - Ho fatto qualcosa di simile per alcuni mesi e i dati sono in gradi C. Era la forza dell'abitudine!
Ripristina Monica - G. Simpson,

Grazie Gavin, una risposta molto simpatica e comprensibile. Proverò i tuoi suggerimenti. È una buona idea tracciare la componente di tendenza stl () e fare una regressione lineare?
Pacomet

1
@pacomet - no, non proprio, a meno che non si adatti un modello che tiene conto dell'autocorrelazione nei residui come ho fatto sopra. Potresti usare GLS per questo ( gls()nel pacchetto nlme). Ma come mostrato sopra per Cairo, e la STL suggerisce per i tuoi dati, la tendenza non è lineare. Pertanto, una tendenza lineare non sarebbe appropriata, poiché non descrive correttamente i dati. Devi provarlo sui tuoi dati, ma un AM come lo mostrerei degraderebbe a una tendenza lineare se si adattava meglio ai dati.
Ripristina Monica - G. Simpson,

1
@ andreas-h Non lo farei; la tendenza STL è sovralimentata. Adatta la GAM alla struttura AR () e interpreta la tendenza. Ciò fornirà un modello di regressione adeguato che ti sarà molto più utile.
Ripristina Monica - G. Simpson,

4

Gavin ha fornito una risposta molto approfondita, ma per una soluzione più semplice e più veloce, mi consiglia di impostare lo stl funzione di t.window parametro su un valore che è un multiplo della frequenza dei ts dati. Vorrei utilizzare la periodicità inferita dell'interesse (ad esempio, un valore di 3660 per le tendenze decadali con i dati di risoluzione diurni). Potresti anche essere interessato al pacchetto stl2 descritto nella tesi dell'autore . Ho applicato il metodo di Gavin ai miei dati ed è anche molto efficace.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.