STL-Trend von Zeitreihen mit R


27

Ich bin neu in R und in der Zeitreihenanalyse. Ich versuche den Trend einer langen (40 Jahre) täglichen Temperatur-Zeitreihe zu finden und versuche verschiedene Annäherungen. Erstens handelt es sich nur um eine einfache lineare Regression und zweitens um die saisonale Zerlegung von Zeitreihen nach Loess.

Bei letzteren scheint die saisonale Komponente über dem Trend zu liegen. Aber wie quantifiziere ich den Trend? Ich möchte nur eine Zahl nennen, die sagt, wie stark dieser Trend ist.

     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

Bildbeschreibung hier eingeben

Antworten:


20

Ich würde mich nicht darum stl()kümmern - die Bandbreite für den Lowess Smoother, der zum Extrahieren des Trends verwendet wird, ist bei weitem zu gering, was zu den kleinen Schwankungen führt, die Sie sehen. Ich würde ein additive Modell verwenden. Hier ist ein Beispiel mit Daten und Modellcode aus Simon Woods Buch über GAMs:

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")

Kairo-Temperaturdaten

Passen Sie ein Modell mit Trend- und Saisonkomponenten an --- Warnung, dies ist langsam:

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)))

Das angepasste Modell sieht folgendermaßen aus:

> 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

und wir können den trend und die saisonbedingten termine über visualisieren

plot(mod$gam, pages = 1)

Kairo passte trend und saisonal

und wenn wir den Trend auf die beobachteten Daten zeichnen wollen, können wir das mit Vorhersage tun über:

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)

Kairo liegt voll im Trend

Oder das Gleiche für das aktuelle Modell:

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)

Modell mit Kairo-Passform

Dies ist nur ein Beispiel, und eine eingehendere Analyse muss möglicherweise die Tatsache berücksichtigen, dass einige Daten fehlen, die oben genannten sollten jedoch ein guter Ausgangspunkt sein.

Bezüglich Ihrer Frage, wie Sie den Trend quantifizieren können - nun, das ist ein Problem, da der Trend weder in Ihrer stl()Version noch in der von mir gezeigten GAM-Version linear ist . Wenn dies der Fall wäre, könnten Sie die Änderungsrate (Steigung) angeben. Wenn Sie wissen möchten, um wie viel sich der geschätzte Trend im Zeitraum der Stichprobe geändert hat, können wir die in den Daten enthaltenen Daten verwenden predund die Differenz zwischen dem Anfang und dem Ende der Serie nur in der Trendkomponente berechnen :

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

Die Temperaturen sind also durchschnittlich 1,76 Grad wärmer als zu Beginn der Aufzeichnung.


Wenn ich mir die Grafik anschaue, kann es zu Verwechslungen zwischen Fahrenheit und Celsius kommen.
Henry

Gut gesehen - ich mache seit ein paar Monaten etwas Ähnliches und die Daten sind in Grad C. War Gewohnheitskraft!
Setzen Sie Monica - G. Simpson am

Danke Gavin, eine sehr nette und verständliche Antwort. Ich werde Ihre Vorschläge versuchen. Ist es eine gute Idee, die stl () - Trendkomponente zu zeichnen und eine lineare Regression durchzuführen?
Pacomet

1
@pacomet - nein, nicht wirklich, es sei denn, Sie passen ein Modell an, das die Autokorrelation in den Residuen berücksichtigt, wie ich es oben getan habe. Sie könnten GLS dafür verwenden ( gls()im Paket nlme). Aber wie das Obige für Kairo zeigt und die STL für Ihre Daten vorschlägt, ist der Trend nicht linear. Ein linearer Trend wäre daher nicht angemessen, da er die Daten nicht richtig beschreibt. Sie müssen es mit Ihren Daten versuchen, aber ein AM, wie ich es zeige, würde sich zu einem linearen Trend verschlechtern, wenn dies den Daten am besten entspricht.
Setzen Sie Monica - G. Simpson am

1
@ andreas-h das würde ich nicht machen; Der STL-Trend ist überpasst. Passen Sie das GAM mit der AR () - Struktur an und interpretieren Sie den Trend. Dadurch erhalten Sie ein geeignetes Regressionsmodell, das für Sie weitaus nützlicher ist.
Setzen Sie Monica - G. Simpson

4

Gavin bot eine sehr ausführliche Antwort, aber für eine einfachere und schnellere Lösung, empfehle ich die Einstellung stl Funktion t.window Parameter auf einen Wert, der ein Vielfaches der ist Frequenz der ts - Daten. Ich würde die abgeleitete Periodizität von Interesse verwenden (z. B. einen Wert von 3660 für dekadische Trends mit Tagesauflösungsdaten). Sie könnten auch an dem in der Dissertation des Autors beschriebenen stl2- Paket interessiert sein . Ich habe Gavins Methode auf meine eigenen Daten angewendet und sie ist auch sehr effektiv.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.