UNIVERSITÉ PARIS OUEST NANTERRE LA DÉFENSE U.F.R. SJAP Année universitaire 2013 2014 Master Droit-Éco Cours de M. Desgraupes Cours de Statistiques et Économétrie Séance 05 1 Analyse de série temporelle 2 1.1 Manipulation des séries temporelles........................ 3 1.2 Représentation graphique.............................. 4 1.3 Agrégation des valeurs............................... 4 2 Lissage 8 2.1 Lissage par moyenne mobile............................ 8 2.2 Lissage par LOESS................................. 11 2.3 Lissage exponentiel................................. 13 2.4 Lissage de Holt-Winters.............................. 15 2.5 Tendance linéaire.................................. 18 1
1 Analyse de série temporelle Séries temporelles On utilise une série temporelle constituée des températures mensuelles moyennes relevées à la station météorologique du Parc Montsouris (Paris 14ème) de janvier 1900 à février 2010. Cette série a été construite pour servir d illustration à cette séance à partir de données fournies par le projet European Climate Assessment & Dataset 1. Données originales : fichier TG_STAID000038.txt dans l archive ECA_blend_tg.zip. Les températures sont indiquées en nombres entiers en dixièmes de degrés Celsius. Chargement des données : dftemp <- read.table("http://bdesgraupes.pagesperso-orange.fr/upx/ Master1/TemperatureMontsouris.R", header=true) > names(dftemp) [1] "mois" "temp" > attach(dftemp) <environment: 0x1044d35f8> attr(,"name") [1] "dftemp" C est un dataframe. On crée une série temporelle stmp à partir du vecteur des températures comme ceci : > stmp<-ts(temp,start=c(1900,1),end=c(2010,2),freq=12) Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 1900 50 52 44 103 131 181 222 185 165 115 77 62 1901 27 0 47 109 149 179 205 191 158 106 46 39 1902 45 26 85 111 110 161 188 176 151 100 60 27 1903 37 62 82 76 142 156 183 175 163 124 70 17... Voir la documentation de la fonction ts et la signification des arguments start, end, frequency et deltat : help(ts) Résumé des données : > summary(stmp) Min. 1st Qu. Median Mean 3rd Qu. Max. -35.0 65.0 113.5 115.7 169.0 249.0 > idx <- which(stmp==max(stmp)) 1. Klein Tank, A.M.G. et co-auteurs, 2002. Daily dataset of 20th-century surface air temperature and precipitation series for the European Climate Assessment. Int. J. of Climatol., 22, 1441-1453. Données et métadonnées disponibles à http ://eca.knmi.nl 2
[1] 1279 > mois[idx] [1] 200607 > idx <- which(stmp==min(stmp)) [1] 674 > mois[idx] [1] 195602 L objet stmp est de classe ts. 1.1 Manipulation des séries temporelles Les attributs d une série temporelle peuvent être récupérés avec les fonctions start, end et frequency : > start(stmp) [1] 1900 1 > end(stmp) [1] 2010 2 > frequency(stmp) [1] 12 La fonction time crée un vecteur de valeurs numériques correspondant aux dates auxquelles la série temporelle a été échantilonnée : time(stmp) Jan Feb Mar Apr May Jun Jul Aug 1900 1900.000 1900.083 1900.167 1900.250 1900.333 1900.417 1900.500 1900.583 1901 1901.000 1901.083 1901.167 1901.250 1901.333 1901.417 1901.500 1901.583 La fonction cycle renvoie un vecteur d indices de chaque valeur à l intérieur d un cycle : cycle(stmp) Jan Feb Mar Apr May Jun Jul Aug Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 1900 1 2 3 4 5 6 7 8 9 10 11 12 1901 1 2 3 4 5 6 7 8 9 10 11 12... C est utile pour retrouver l indice au sein d un cycle. Par exemple : > cycle(stmp)[temp==max(temp)] [1] 7 3
Cette commande indique que la température moyenne maximale a été relevée pendant un mois de juillet (=7). La fonction deltat permet d obtenir l intervalle de temps entre chaque observation sous forme d une fraction de la période (ici 1/12) : > deltat(stmp) [1] 0.08333333 On peut extraire une partie d une série temporelle au moyen de la fonction window. Cette fonction accepte les mêmes arguments start, end, frequency et deltat que la fonction ts. Par exemple, extrayons une sous-série avec les données allant de janvier 1990 à décembre 1999 : st9099 <- window(stmp, start = c(1990,1), end = c(1999,12)) R connaît aussi un autre type d objet appelé série temporelle multiple (mts) : c est comme un dataframe dont chaque colonne serait une série temporelle. 1.2 Représentation graphique La fonction plot a un comportement particulier quand on l applique à un objet de classe ts : > plot(stmp) Le graphe est représenté sur la figure 1. Avec la fonction window, on peut tracer la courbe d une partie seulement de la série (ici de 1980 à 2010) : > plot(window(stmp, start = c(1980,1), end = c(2010,2)), main='1980-2010',xlab='',ylab='températures') Le graphe est représenté sur la figure 2. La fonction boxplot couplée avec la fonction cycle permet de construire des boîtes à moustache pour chacune des périodes d un cycle : > boxplot(stmp ~ cycle(stmp)) Le vecteur cycle(stmp) est utilisé ici implicitement comme un facteur. Le graphe est représenté sur la figure 3. Cela met en évidence quelques valeurs aberrantes (outliers). 1.3 Agrégation des valeurs La fonction aggregate permet de calculer des statistiques (telles que moyenne, sommes, etc.) sur des sous-ensembles d une série temporelle. L argument nfrequency est le nombre d observations à utiliser par unité de temps. Il faut spécifier une valeur qui soit un diviseur de la fréquence de la série elle-même. Par exemple, pour une série de fréquence 12, si la valeur de nfrequency est 1, on obtiendra des statistiques par année. Si la valeur de nfrequency est 2, on obtiendra des statistiques par semestres car la fonction créera des sous-ensembles de 6 valeurs. Si la valeur de nfrequency est 4, on obtiendra des statistiques par trimestres. Dans l argument FUN, on indique la fonction à appliquer. Par exemple, calculons les valeurs moyennes par semestre sur les dix dernières années : > stmp0009 <- window(stmp, start = c(2000,1), end = c(2009,12)) 4
stmp 0 50 100 150 200 250 1900 1920 1940 1960 1980 2000 Time FIGURE 1 Graphique de la série stmp. Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 2000 50 77 92 114 167 188 183 210 176 127 89 78 2001 58 65 96 101 168 183 206 211 146 158 75 42 2002 62 85 101 122 146 191 195 199 164 130 97 73 2003 36 46 112 127 157 218 216 244 174 105 93 60 2004 56 65 81 120 146 188 197 208 181 131 85 43 2005 60 42 87 124 157 204 211 195 186 161 73 48 2006 39 43 70 118 159 199 249 183 200 156 99 61 2007 84 91 90 163 165 192 193 186 161 124 82 52 2008 73 76 82 111 179 188 207 196 156 120 85 42 2009 23 50 86 136 160 184 209 220 177 135 108 50 > aggregate(stmp0009, FUN=mean, nfreq=2) Time Series: Start = c(2000, 1) End = c(2009, 2) Frequency = 2 [1] 114.6667 143.8333 111.8333 139.6667 117.8333 143.0000 [7] 116.0000 148.6667 109.3333 140.8333 112.3333 145.6667 [13] 104.6667 158.0000 130.8333 133.0000 118.1667 134.3333 5
1980 2010 Températures 0 50 100 150 200 250 1980 1985 1990 1995 2000 2005 2010 FIGURE 2 Graphique de 1980 à 2010. [19] 106.5000 149.8333 Cela fait 20 valeurs. Les moyennes annuelles sont obtenues comme ceci : > aggregate(stmp0009, FUN=mean, nfreq=1) Time Series: Start = 2000 End = 2009 Frequency = 1 [1] 129.2500 125.7500 130.4167 132.3333 125.0833 129.0000 [7] 131.3333 131.9167 126.2500 128.1667 Voici les minima par trimestre : > aggregate(stmp0009, FUN=min, nfreq=4) Qtr1 Qtr2 Qtr3 Qtr4 2000 50 114 176 78 2001 58 101 146 42 2002 62 122 164 73 6
0 50 100 150 200 250 1 2 3 4 5 6 7 8 9 10 11 12 FIGURE 3 Boîtes à moustache par cycle. 2003 36 127 174 60 2004 56 120 181 43 2005 42 124 186 48 2006 39 118 183 61 2007 84 163 161 52 2008 73 111 156 42 2009 23 136 177 50 On peut de même avoir un résumé par année comme ceci > aggregate(stmp0009, FUN=summary, nfreq=1) Time Series: Start = 2000 End = 2059 Frequency = 1 [1] 50.00 86.25 120.50 129.20 177.80 210.00 42.00 72.50 [9] 123.50 125.80 171.80 211.00 62.00 94.00 126.00 130.40 [17] 170.80 199.00 36.00 84.75 119.50 132.30 184.50 244.00 [25] 43.00 77.00 125.50 125.10 182.80 208.00 42.00 69.75 [33] 140.50 129.00 188.20 211.00 39.00 67.75 137.00 131.30 7
[41] 187.00 249.00 52.00 88.50 142.50 131.90 170.20 193.00 [49] 42.00 80.50 115.50 126.20 181.20 207.00 23.00 77.00 [57] 135.50 128.20 178.80 220.00 Le résultat n est pas facile à lire. Les valeurs se lisent six par six : ce sont les six quantités renvoyées par summary comme dans : > summary(window(stmp, start = c(2000,1), end = c(2000,12))) Min. 1st Qu. Median Mean 3rd Qu. Max. 50.00 86.25 120.50 129.20 177.80 210.00 Une manière plus lisible d afficher ces données serait sous forme d une matrice de 10 lignes et 6 colonnes : > agg <- aggregate(stmp0009,fun=summary,nfreq=1) > matrix(agg,ncol=6, nrow=10) [,1] [,2] [,3] [,4] [,5] [,6] [1,] 50.00 171.80 119.5 42.00 187.0 115.5 [2,] 86.25 211.00 132.3 69.75 249.0 126.2 [3,] 120.50 62.00 184.5 140.50 52.0 181.2 [4,] 129.20 94.00 244.0 129.00 88.5 207.0 [5,] 177.80 126.00 43.0 188.20 142.5 23.0 [6,] 210.00 130.40 77.0 211.00 131.9 77.0 [7,] 42.00 170.80 125.5 39.00 170.2 135.5 [8,] 72.50 199.00 125.1 67.75 193.0 128.2 [9,] 123.50 36.00 182.8 137.00 42.0 178.8 [10,] 125.80 84.75 208.0 131.30 80.5 220.0 Voici la représentation graphique des valeurs agrégées par année (voir la figure 4) : > plot(aggregate(stmp, FUN=mean, nfreq=1)) Pour voir les boîtes à moustache par périodes de 4 mois (nfreq=3), on écrirait l instruction suivante : semestres <- aggregate(stmp, FUN=mean, nfreq=3) boxplot(semestres ~ cycle(semestres)) 2 Lissage 2.1 Lissage par moyenne mobile Le lissage par moyenne mobile est exécuté par la fonction decompose. Par exemple : > dec <- decompose(stmp) > class(dec) [1] "decomposed.ts" > names(dec) 8
aggregate(stmp, FUN = mean, nfreq = 1) 100 105 110 115 120 125 130 1900 1920 1940 1960 1980 2000 Time FIGURE 4 Valeurs agrégées par année. [1] "x" "seasonal" "trend" "random" "figure" [6] "type" L objet dec obtenu est de classe decomposed.ts. dans cet objet, on récupère les séries représentant la tendance, les variations saisonnières et les résidus sous la forme dec$trend, dec$seasonal et dec$random respectivement. Le terme dec$figure représente les variations saisonnières sur un cycle seulement tandis que dec$seasonal représente la répétition de cette figure cyclique sur toute la longueur de la série. dec$figure [1] -75.714832-67.218654-37.530199-8.413991 30.750000 59.816131 [7] 79.621560 76.504969 48.665520 5.109327-43.060780-68.529052 La fonction plot se comporte de manière particulière avec les objets de classe decomposed.ts comme on peut le voir sur la figure 5. La fonction plot, lorsqu elle est appliquée au résultat d une décomposition, produit quatre graphiques superposés représentant la série de départ, la tendance, la saisonnalité et les résidus : > plot(dec) On peut aussi effectuer à la main le calcul des moyennes mobiles : 9
Decomposition of additive time series random 60 20 20 seasonal 50 0 50 trend 100 120 140 observed 0 50 150 250 1900 1920 1940 1960 1980 2000 Time FIGURE 5 Graphique de décomposition par moyenne mobile. > len <- length(temp) > mmob<-vector(length=len) > for (i in 7:len) { mmob[i] <- sum( c(temp[i-6]/2, temp[(i-5):(i+5)], temp[i+6]/2) )/12 } On obtient les mêmes valeurs que dans dec$trend. Voici les 24 premières : > dec$trend[1:24] [1] NA NA NA NA NA NA [7] 114.6250 111.5000 109.4583 109.8333 110.8333 111.5000 [13] 110.7083 110.2500 110.2083 109.5417 107.8750 105.6250 [19] 105.4167 107.2500 109.9167 111.5833 110.0417 107.6667 > mmob[1:24] [1] 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 [7] 114.6250 111.5000 109.4583 109.8333 110.8333 111.5000 [13] 110.7083 110.2500 110.2083 109.5417 107.8750 105.6250 [19] 105.4167 107.2500 109.9167 111.5833 110.0417 107.6667 10
Calcul à la main des variations saisonnières : on élimine les 6 valeurs initiales et finales qui sont NA et on soustrait la tendance dans la série obtenue, on calcule les moyennes pour chacun des 12 mois. > len <- length(temp) > idx <- 7:(len-6) > msaison <- by(temp[idx]-mmob[idx],cycle(stmp)[idx],mean) La moyenne de ces moyennes mensuelles est proche de 0 : mean(msaison) [1] 0.02095554 On soustrait cette moyenne pour obtenir la saisonnalité définitive : > saisons <- as.vector(msaison-mean(msaison)) [1] -75.531277-67.035099-37.346644-8.230436 30.933555 [6] 59.999687 80.055560 76.659347 48.373540 4.665971 [11] -43.697179-68.847026 Remarque : à la fin de ce calcul, on ne trouve pas tout-à-fait les mêmes valeurs que dans le terme dec$figure ci-dessus car R fait quelques corrections de lissage sur les valeurs initiales et finales de la série. Finalement le vecteur des résidus est obtenu en retirant à la fois la tendance et la saisonnalité : > residus <- temp-mmob-saisons[cycle(stmp)] 2.2 Lissage par LOESS La technique LOESS est implémentée dans R pour les séries temporelles par la fonction stl. Cette fonction renvoie un objet de classe stl comportant en particulier une composante appelée time.series qui est une série temporelle multiple composée de colonnes appelées trend, seasonal et remainder, correspondant respectivement à la tendance, l effet saisonnier et le reste (résidus). Le premier argument de la fonction stl est la série temporelle et le second argument (appelé s.window) est soit le mot-clé periodic, soit une valeur numérique indiquant la taille de la fenêtre pour extraire localement les données. Voici un exemple d utilisation : > loessdec <- stl(stmp, s.window="periodic") > class(loessdec) [1] "stl" > names(loessdec) [1] "time.series" "weights" "call" "win" [5] "deg" "jump" "inner" "outer" On obtient : 11
remainder 60 20 20 trend 100 120 140 seasonal 50 0 50 data 0 50 150 250 1900 1920 1940 1960 1980 2000 time FIGURE 6 Graphique de décomposition par LOESS. loessdec$time.series seasonal trend remainder Jan 1900-75.670018 113.95005 11.71996450 Feb 1900-67.051760 113.90133 5.15043417 Mar 1900-37.638389 113.85260-32.21420805 Apr 1900-8.245680 113.57152-2.32583905 May 1900 30.828846 113.29044-13.11928595... La fonction plot, comme précédemment, produit quatre graphiques : > plot(loessdec) Le graphe est représenté sur la figure 6. Exercice : refaisons les calculs en se restreignant aux 20 dernières années : > stmp20 <- window(stmp, start = c(1990,1), end = c(2010,2)) > loessdec20 <- stl(stmp20, s.window="periodic") > plot(loessdec20, main='loess 1990-2010') Le graphe est représenté sur la figure 7. 12
LOESS 1990 2010 remainder 30 10 10 30 trend 115 125 135 seasonal 50 0 50 data 50 150 250 1990 1995 2000 2005 2010 time FIGURE 7 Graphique loess20. 2.3 Lissage exponentiel Afin d obtenir un lissage exponentiel, on utilise la fonction HoltWinters avec les arguments beta et gamma égaux à 0 (FALSE) : > expdec <- HoltWinters(stmp, beta=0, gamma=0) Holt-Winters exponential smoothing with trend and additive seasonal component. Call: HoltWinters(x = stmp, beta = 0, gamma = 0) Smoothing parameters: alpha: 0.1073702 beta : 0 gamma: 0 Coefficients: [,1] a 122.8469716 b -0.4605186 13
s1-64.4618056 s2-1.7951389 s3 39.8715278 s4 72.1215278 s5 106.1215278 s6 72.2465278 s7 54.2881944 s8 3.9131944 s9-35.0868056 s10-50.7534722 s11-84.9618056 s12-111.5034722 L objet expdec est de classe HoltWinters et comporte les termes suivants : > class(expdec) [1] "HoltWinters" > names(expdec) [1] "fitted" "x" "alpha" [4] "beta" "gamma" "coefficients" [7] "seasonal" "SSE" "call" En particulier, le terme SSE représente la valeur minimale de la somme des carrés des erreurs de prédiction à une période (SCEP1) : > expdec$sse [1] 886321.7 Les coefficients a, b, s1,..., s12 sont les valeurs initales des suites de récurrence : niveau estimé a t, pente b t, effets saisonniers s t. Le terme fitted est une série temporelle multiple comportant les valeurs estimées ˆx, le niveau, la tendance et la saisonnalité. Voici un extrait : expdec$fitted xhat level trend season Jan 1901 27.734241453 113.15657-0.4605186-84.961806 Feb 1901 0.653220476 112.61721-0.4605186-111.503472 Mar 1901 47.164232073 112.08656-0.4605186-64.461806 Apr 1901 109.352746458 111.60840-0.4605186-1.795139 May 1901 150.521020014 111.11001-0.4605186 39.871528... On peut les représenter sur un même graphique grâce à la fonction plot : > plot(expdec$fitted) Le graphe est représenté sur la figure 8. Le α obtenu (0.1073702) indique un faible degré de lissage : la valeur de référence est de l ordre de 0.2. En règle générale, on n utilise pas ce type de lissage sur de longues séries. Refaisons les calculs en se restreignant aux 20 dernières années : 14
expdec$fitted season 100 0 50 trend 0.6 0.4 level xhat 100 120 140 0 50 150 250 1900 1920 1940 1960 1980 2000 Time FIGURE 8 Graphique expdec. > stmp20 <- window(stmp, start = c(1990,1), end = c(2010,2)) > expdec20 <- HoltWinters(stmp20,beta=0,gamma=0) > plot(expdec20$fitted, main='temperatures 1990-2010') Le graphe est représenté sur la figure 9. 2.4 Lissage de Holt-Winters On utilise aussi la fonction HoltWinters, comme dans la section précédente, mais en laissant cette fois R calculer une estimation pour les arguments beta et gamma : > hwdec <- HoltWinters(stmp) Holt-Winters exponential smoothing with trend and additive seasonal component. Call: HoltWinters(x = stmp) Smoothing parameters: alpha: 0.05181304 15
Temperatures 1990 2010 trend 1.2 0.8 100 0 50 100 level season 110 130 xhat 0 50 150 1995 2000 2005 2010 Time FIGURE 9 Graphique de lissage exponentiel de 1990 à 2010. beta : 0.01196868 gamma: 0.1151555 Coefficients: [,1] a 119.3414745 b -0.0174726 s1-31.4959234 s2 1.4535040 s3 38.6182262 s4 67.9116069 s5 86.3199309 s6 83.9129152 s7 50.9376981 s8 11.7966902 s9-34.1022245 s10-66.2971774 s11-71.1455101 s12-59.9011504 Le graphe est représenté sur la figure 10 : 16
Temperatures 1900 2010 season 100 0 50 trend level 0.5 0.3 0.1 0.1 95 105 115 125 xhat 0 50 150 1900 1920 1940 1960 1980 2000 Time FIGURE 10 Graphique de lissage par Holt-Winters (α estimé). > plot(hwdec$fitted, main='temperatures 1900-2010') Le α obtenu (0.05181304) indique faible degré de lissage. Refaisons les calculs en imposant α = 0.2 : > hwdec2 <- HoltWinters(stmp, alpha=0.2) Holt-Winters exponential smoothing with trend and additive seasonal component. Call: HoltWinters(x = stmp, alpha = 0.2) Smoothing parameters: alpha: 0.2 beta : 0.003181335 gamma: 0.1313225 Coefficients: [,1] a 115.356917447 b -0.008582128 17
Temperatures 1900 2010 alpha = 0.2 season 100 0 50 trend 0.5 0.3 0.1 level 90 110 130 xhat 0 50 150 1900 1920 1940 1960 1980 2000 Time FIGURE 11 Graphique de lissage par Holt-Winters (α = 0.2). s1-30.913977104 s2 1.998054505 s3 38.243373411 s4 67.062195048 s5 85.151916346 s6 82.846386614 s7 50.240400177 s8 11.208319621 s9-34.649536118 s10-66.780552149 s11-70.759405432 s12-59.025111291 Le graphe est représenté sur la figure 11 : > plot(hwdec2$fitted, main='temperatures 1900-2010 - alpha = 0.2') 2.5 Tendance linéaire On peut rechercher un modèle linéaire dans une série temporelle comme dans n importe quel vecteur d observations. Ici, le temps sert de variable explicative. On utilise la fonction lm : 18
> reg <- lm(dec$trend ~ time(stmp)) Call: lm(formula = dec$trend ~ time(stmp)) Coefficients: (Intercept) time(stmp) -235.5496 0.1797 > summary(reg) Call: lm(formula = dec$trend ~ time(stmp)) Residuals: Min 1Q Median 3Q Max -20.1710-3.6531 0.0522 3.3664 19.6416 Coefficients: Estimate Std. Error t value Pr(> t ) (Intercept) -2.355e+02 9.727e+00-24.22 <2e-16 *** time(stmp) 1.797e-01 4.975e-03 36.13 <2e-16 *** --- Signif. codes: 0 *** 0.001 ** 0.01 * 0.05. 0.1 1 Residual standard error: 5.674 on 1308 degrees of freedom (12 observations deleted due to missingness) Multiple R-squared: 0.4994, Adjusted R-squared: 0.4991 F-statistic: 1305 on 1 and 1308 DF, p-value: < 2.2e-16 Représentation graphique (voir la figure 12) : > plot(time(stmp),dec$trend,type='l',main="tendance lineaire", ylab="temperature") > abline(reg) 19
Tendance lineaire Temperature 100 110 120 130 140 1900 1920 1940 1960 1980 2000 time(stmp) FIGURE 12 Régression linéaire sur les températures. 20