En vue de se préparer à l’examen (qui aura lieu vendredi prochain), je mets en ligne quelques exercices de séries temporelles, ainsi que quelques questions à choix multiples. On regarde tout ça mercredi.
Category Archives: M1-Time Series
Prévision de l’intérêt pour le chocolat, avec des modèles ARIMA
Hier en cours, on s’était lancé sur la prévision de la série obtenue sur Google Trends pour le mot clé “chocolat“. La série est la suivante
> url = "http://freakonometrics.free.fr/report-chocolat.csv" > report = read.csv(url,skip=6, + header=FALSE,nrows=636) > X=report$V2 > plot(X,type="l")
Comme on l’avait évoqué, c’est plus simple de construire un modèle ARIMA sur des séries mensuelles qu’hebdomadaire. Donc on va mensualiser la série. Ah oui, on va aussi enlever les deux dernières années pour faire une comparaison de modèles (en confrontant les prévision avec les observations)
> date1=substr(as.character(report$V1),1,10) > date2=substr(as.character(report$V1),14,23) > d1=as.Date(date1,"%Y-%m-%d") > d2=as.Date(date2,"%Y-%m-%d") > Vect_J=Vect_M=Vect_X=Vect_A= NULL > for(i in 1:length(d1)){ + jours = seq(d1[i],d2[i],length=7) + mois = as.POSIXlt(jours)$mon+1 + annees = as.POSIXlt(jours)$year+1900 + donnees = rep(X[i],7) + Vect_J = c(Vect_J,jours) + Vect_M = c(Vect_M,mois) + Vect_A = c(Vect_A,annees) + Vect_X = c(Vect_X,donnees) + } > base = data.frame(J = Vect_J,M = Vect_M, + A = Vect_A,X = Vect_X) > base$AM = base$A*100+base$M > Y = tapply(base$X,as.factor(base$AM),mean) > Z = ts(as.numeric(Y[1:(146-24)]), + start=c(2004,1),frequency=12) > plot(Z)
Compte tenu de l’amplitude croissante des cycles, il peut être intéressant, ici, de passer au logarithme de la série. Et comme on observe une rupture dans la tendance (linéaire au début, et relativement constante ensuite), on peut ajuste une régression linéaire avec une rupture (mais continue)
> plot(as.numeric(Z),type="l") > X=log(as.numeric(Z)) > T=1:length(X) > db=data.frame(X,T) > trend=lm(X~T+I((T-80)*(T>80)),data=db) > plot(X,type="l") > lines(predict(trend),col="red")
C’est le résidu de cette série qu’on va chercher à modéliser,
> Y=residuals(trend) > plot(Y,type="l")
Pour modéliser cette série, on peut commencer par regarder sa série d’autocorrélation
> plot(acf(Y,lag=36),lwd=5)
et d’autocorrélation partielles,
> plot(pacf(Y,lag=36),lwd=5)
La série est stationnaire, mais il y a une composante cyclique forte (peut être une racine unité saisonnière ?). On peut tenter un premier modèle AR, ou ARMA (avec un AR les résidus ne sont pas un bruit blanc).
> model1 = arima(Y,order=c(12,0,12), + seasonal = list(order = c(0, 0, 0), period = 12))
La série des résidus est ici un bruit blanc
> E=residuals(model1) > plot(acf(E,lag=36),lwd=5)
On peut alors utiliser ce modèle pour faire des prévisions, sur la série initiale (avant de prendre le logarithme, et d’ajuster une tendance)
> futur=length(X)+1:24 > Yp=predict(model1,n.ahead=24)$pred+ + predict(trend,newdata=data.frame(T=futur)) > Xp=exp(as.numeric( + Yp+.5*predict(model1,n.ahead=24)$se^2)) > plot(as.numeric(Z),type="l",xlim=c(1,150)) > lines(futur,Xp,col="red") > Y2=tapply(base$X,as.factor(base$AM),mean) > obs_reel=as.numeric(Y2[(146-24)+1:24]) > lines(futur,obs_reel,col="blue")
avec en rouge notre modèle, et en bleu les vraies observations. On peut alors calculer la somme des carrés des erreurs, sur ces 24 observations,
> sum( (obs_reel-Xp)^2 ) [1] 190.9722
Mais on peut tenter d’autres modèles, par exemple en changeant la tendance (on ne va pas le faire) ou en changeant le modèle ARIMA (en intégrant une racine unité saisonnière)
> model3=arima(Y,order=c(0,0,2), + seasonal = list(order = c(0, 1, 1), period = 12)) > E=residuals(model3) > model3 Coefficients: ma1 ma2 sma1 0.2246 0.3034 -0.9999 s.e. 0.0902 0.0925 0.3503 sigma^2 estimated as 0.002842: log likelihood = 152.37, aic = -296.75
On vérifie que les résidus sont effectivement un bruit blanc
> plot(acf(E,lag=36),lwd=5) > Box.test(E,lag=12) Box-Pierce test data: E X-squared = 6.326, df = 12, p-value = 0.8988
On peut alors faire une prévision sur notre série brute,
> futur=length(X)+1:24 > Yp=predict(model3,n.ahead=24)$pred+ + predict(trend,newdata=data.frame(T=futur)) > Xp=exp(as.numeric( + Yp+.5*predict(model3,n.ahead=24)$se^2)) > plot(as.numeric(Z),type="l",xlim=c(1,150)) > lines(futur,as.numeric(Xp),col="red") > Y2=tapply(base$X,as.factor(base$AM),mean) > obs_reel=as.numeric(Y2[(146-24)+1:24]) > lines(futur,obs_reel,col="blue")
La somme des carrés des erreurs est ici un peu plus faible
> sum( (obs_reel-Xp)^2 ) [1] 173.8138
C’est à dire que ce second modèle est meilleur que le précédant, sur les deux dernières années. C’est probablement celui que l’on devrait utiliser pour faire des prévisions pour les années à venir (à moins qu’en continuant l’analyse on n’en trouve un meilleur).
Forecasts with ARIMA Models
In our time series class this morning, I was discussing forecasts with ARIMA Models. Consider some simple stationnary AR(1) simulated time series
> n=95 > set.seed(1) > E=rnorm(n) > X=rep(0,n) > phi=.85 > for(t in 2:n) X[t]=phi*X[t-1]+E[t] > plot(X,type="l")
If we fit an AR(1) model,
> model=arima(X,order=c(1,0,0), + include.mean = FALSE) > P=predict(model,n.ahead=20) > plot(P$pred) > lines(P$pred+2*P$se,col="red") > lines(P$pred-2*P$se,col="red") > abline(h=0,lty=2) > abline(h=2*P$se[20],lty=2,col="red") > abline(h=-2*P$se[20],lty=2,col="red")
we observe the exponential decay of the forecast towards 0, and the increasing confidence interval (where the variance increases, from the variance of the white noise to the variance of the stationnary time series). Plain lines are conditional forecast (given our latest observation, since the AR(1) is a first order Markov process), and dotted lines are unconditional. Let us store some values, to use them as benchmark
> s=P$se[20] > y=P$pred
If we fit a MA(1) model
> model=arima(X,order=c(0,0,1), + include.mean = FALSE) > P=predict(model,n.ahead=20) > plot(P$pred) > lines(P$pred+2*P$se,col="red") > lines(P$pred-2*P$se,col="red") > abline(h=0,lty=2) > abline(h=2*s,lty=2,col="red") > abline(h=-2*s,lty=2,col="red") > lines(y,col="grey")
after two lags, the forecast is null, and the (conditional) variance remains constant. But if we consider a moving average process with a longer order,
> model=arima(X,order=c(0,0,14), + include.mean = FALSE) > P=predict(model,n.ahead=20) > plot(P$pred) > lines(P$pred+2*P$se,col="red") > lines(P$pred-2*P$se,col="red") > abline(h=0,lty=2) > abline(h=2*s,lty=2,col="red") > abline(h=-2*s,lty=2,col="red") > lines(y,col="grey")
we get an output that can be compared with the AR(1) processes. Which makes sense since our AR(1) process can also be seen as a MA(∞), with infinite order.
But if we think that our time series is not stationary, an we fit an integrated model
> model=arima(X,order=c(0,1,0), + include.mean = FALSE) > P=predict(model,n.ahead=20) > plot(P$pred) > lines(P$pred+2*P$se,col="red") > lines(P$pred-2*P$se,col="red") > abline(h=0,lty=2) > abline(h=2*s,lty=2,col="red") > abline(h=-2*s,lty=2,col="red") > lines(y,col="grey")
we observe the (standard) martingale property: the forecast is flat, and the confidence interval keeps increasing, and actually, the variance increases towards infinity (at a linear rate). So one should be very careful when differentiation a time series… it will have a huge impact on the forecasts….
Séries Temporelles, Exercices
Quelques exercices de séries temporelles, histoire de travailler un peu le cours… En TP, on travaillera davantage les aspects computationnels.
Contraintes sur les autocorrélations d’une série temporelle stationnaire
En cours de séries temporelles, ce matin, on a fini avec les contraintes sur les auto-corrélations, compte tenu du fait que la matrice d’autocorrélations doit être positive. On l’a vu, la matrice d’autocorrélations et la matrice de Toeplitz de déterminant
Avec la règle qu’on apprend tout petit pour calculer les déterminants 3×3, on a la somme des produits des termes pourpres, bleus et verts
à laquelle on retranche la somme des produits des termes verts, bleus et oranges,
Bref, on obtient assez facilement que
soit
avec de plus les corrélations dans l’intervalle ,
La région admissible pour la paire de corrélations est alors la région bleue ci-dessous
Décomposition(s) de Séries Temporelles
La semaine dernière, pour le TP du cours de série temporelle, on avait parlé de décomposition de séries temporelles. On part d’une série temporelle , et on va considérer une décomposition de la forme
par exemple une tendance linéaire, et un cycle annuel,
Considérons la série suivante
> autoroute=read.table( + "http://freakonometrics.free.fr/autoroute.csv", + header=TRUE,sep=";") > a7=autoroute$a007 > X=ts(a7,start = c(1989, 9), frequency = 12)
correspondant à du trafic sur l’autoroute (A7)
> plot(X,xlim=c(1989,2000))
Pour estimer la tendance, on va faire une régression linéaire, sur le temps, à partir de la base suivante
> T=time(X) > base=data.frame(Y=a7,X1=as.numeric(T))
Le modèle est ici
> reg1=lm(Y~X1,data=base)
ce qui permet de faire une prévision sur les données passées, mais aussi futures,
> tendance1=predict(reg1) > T=as.numeric(T) > lines(T,tendance1,col="red",lwd=3) > futur=seq(max(T)+1/12,length=36,by=1/12) > tendance2=predict(reg1, + newdata=data.frame(X1=futur)) > lines(futur,tendance2,col="red")
Voilà pour la tendance. Pour le cycle, on va ajuste un modèle de la forme suivante
sur la série des résidus
> base$Y2=residuals(reg1)
Cette fois, on va définir le mois de la date
> base$mois=round(base$X1-t + trunc(base$X1),digit=4)
Et on régresse le résidu sur le mois
> reg2=lm(Y2~0+as.factor(mois),data=base)
Là encore, on peut faire une régression sur les données passées
> cycle1=predict(reg2) > lines(T,tendance1+cycle1,col="blue",lwd=3)
mais aussi sur les données futures,
> moisfutur=round(futur-trunc(futur),4) > cycle2=predict(reg2,newdata= + data.frame(mois=moisfutur)) > lines(futur,tendance2+cycle2,col="blue")
Cela dit, pour les données futures, on peut aussi tenter de rajouter une région de confiance, en tenant compte de l’erreur d’ajustement,
> E=residuals(reg2) > hist(E) > 1.96*sqrt(var(E)) [1] 5637.897
On peut alors facilement ajouter notre région de confiance avec
> polygon(c(futur,rev(futur)), + c(tendance2+cycle2-1.96*sqrt(var(E)), + rev(tendance2+cycle2+1.96*sqrt(var(E)))), + col="yellow",border=NA)
Et voilà…. On peut quand même vérifier que le bruit est effectivement non-autocorrélé, et c’est le cas ici
> plot(acf(E))
Comme on l’a vu en TP, ajuster une droite de régression c’est bien ici, mais peut être qu’on peut envisager un ajustement local. Par exemple prendre la moyenne autour de la date qui nous intéresse, +/- 6 mois (techniquement, si on rajoute 6 mois avant et après, on aura un soucis, alors on fait une petite correction au bord),
ce qui correspond à un lissage par moyenne mobile.
> n=length(X) > F=rep(NA,n) > for(t in 7:(n-7)) F[t]=1/12*(sum(X[(t-5):(t+5)])+ (X[t-6]+X[t+6])/2) > lines(T,F,lwd=3,col="purple")
On voit ici – par notre ajustement non-paramétrique – que l’ajustement d’une tendance linéaire n’était pas si mauvais que ça
Par contre, pour des séries où la tendance n’est clairement pas linéaire, le lissage par moyenne mobile permet d’avoir une bonne estimation de la tendance de fond
> sncf=read.table( + "http://freakonometrics.free.fr/sncf.csv", + header=TRUE,sep=";") > train=as.vector(t(as.matrix(sncf[,2:13]))) > X=ts(train,start = c(1963, 1), frequency = 12) > plot(X) > n=length(X) > F=rep(NA,n) > for(t in 7:(n-7)) F[t]=1/12*(sum(X[(t-5):(t+5)])+(X[t-6]+X[t+6])/2) > lines(as.numeric(time(X)), + F,lwd=3,col="purple")
On continuera en cours cette semaine autour du lissage, par moyenne mobile, et avec du lissage exponentiel ensuite. A suivre donc.
TP, Séries Temporelles
Deux bases pour illustrer le TP de séries temporelles. La première est du trafic sur autoroute, en France
> autoroute=read.table( + "http://freakonometrics.free.fr/autoroute.csv", + header=TRUE,sep=";") > a7=autoroute$a007 > X=ts(a7,start = c(1989, 9), frequency = 12) > T=time(X)
et on utilisera aussi du traffic sur le réseau de la SNCF
> sncf=read.table( + "http://freakonometrics.free.fr/sncf.csv", + header=TRUE,sep=";") > train=as.vector(t(as.matrix(sncf[,2:13]))) > X=ts(train,start = c(1963, 1), frequency = 12)
Trafic Journalier sur les Bus Parisiens
Sur http://opendata.stif.info/, on peut avoir accès à des trafics journaliers sur des lignes de bus en région parisienne.
> base1=read.csv( "/home/charpentier/Téléchargements/validations-sur-le-reseau-de-surface-nombre-de-validations-par-jour-1er-sem (1).csv", sep=";") > base1=base1[-which(base1$LIBELLE_LIGNE%in% c("Inconnu","NON DEFINI")),] > dim(base1) [1] 991842 8
Il faut faire un peu attention avec le trafic, qui est ici un facteur (à cause de réponses du type ‘moins de 5’)
> base1$NB_VALD=as.numeric( + as.character(base1$NB_VALD))
On peut considerer une ligne de bus particulière, par exemple entre la porte de St-Cloud et la Bibliothèque Nationale,
> id="PARIS-16 (Porte de St-Cloud) - PARIS-13 (Bibliothèque F. Mitterrand)"
ce qui pourrait être la ligne 62,
On peut spécifier ensuite la catégorie du titre de transport, comme une carte navigo, ou une carte imagine’r (étudiants et scolaires)
> B_navigo=base1[(base1$LIBELLE_LIGNE==id)&(base1$CATEGORIE_TITRE=="NAVIGO"),] > B_ir=base1[(base1$LIBELLE_LIGNE==id)&(base1$CATEGORIE_TITRE=="IMAGINE R"),]
Comme on va visualiser une série temporelle, on doit trier en fonction de la date
> B_navigo$date=as.Date(B_navigo$JOUR,"%d/%m/%Y") > B_navigo=B_navigo[order(B_navigo$date),]
Sur les 6 premiers mois de 2015, on observe la série temporelle suivante (avec une carte navigo)
> plot(B_navigo$date,B_navigo$NB_VALD,type="l")
Si on regarde en fonction du jour de la semaine, du dimanche au samedi,
> jour=as.POSIXlt(B_navigo$date)$wday > x=B_navigo$NB_VALD > plot(jour,x,axes=FALSE,ylim=c(-1000,max(x))) > Z_m=tapply(as.numeric(x),as.factor(jour),mean) > lines(as.numeric(names(Z_m)),Z_m,col="red") > axis(2) > text(0:6,rep(-1000,7), + c("D","L","M","M","J","V","S"))
on obtient
avec une tendance qui ne présente pas trop de surprise : beaucoup de monde les jours de semaine, moins le samedi, et encore moins le dimanche. Pour la carte étudiante, on a une tendance un peu différente
> B_ir$date=as.Date(B_ir$JOUR,"%d/%m/%Y") > B_ir=B_ir[order(B_ir$date),] > plot(B_ir$date,B_ir$NB_VALD,type="l")
avec sur les premiers mois de 2016,
On retrouve les deux périodes de vacances, et une étrange tendance: une hausse jusqu’en avril, puis une décroissance (sur les jours de semaine). Si on regarde en fonction du jour de la semaine
> jour=as.POSIXlt(B_ir$date)$wday > x=B_ir$NB_VALD > plot(jour,x,axes=FALSE,ylim=c(-1000,max(x))) > Z_m=tapply(as.numeric(x),as.factor(jour),mean) > lines(as.numeric(names(Z_m)),Z_m,col="red") > axis(2) > text(0:6,rep(-1000,7), + c("D","L","M","M","J","V","S"))
On a ici, là encore, beaucoup moins de trafic le dimanche que les jours de la semaine,
On verra – si on a le temps – pour utiliser ces données dans le cadre du cours de séries temporelles.
Manipuler des Séries Chronologiques
Ce matin en cours, on a vu un peu comment manipuler des séries temporelles, et en particulier comme jouer avec l’échelle de temps (passer de données hebdomadaire à de données mensuelles, par exemple).
Pour commencer, travaillons un peu sur les données extraites de google.fr/trends/ par exemple sur le mot clé fièvre,
report = read.csv( "http://freakonometrics.free.fr/report-fievre.csv", skip=6,header=FALSE,nrows=626) X=report$V2 plot(X,type="l")
Au lieu d’avoir un vecteur, on peut créer un format de série temporelle (hebdomadaire )
X_h=ts(X,start=c(2004,3),frequency=52) plot(X_h)
On va essayer d’agréger les données pour les rendre mensuelles
date1=substr(as.character(report$V1),1,10) date2=substr(as.character(report$V1),14,23) d1=as.Date(date1,"%Y-%m-%d") d2=as.Date(date2,"%Y-%m-%d") d1[2]-d1[1] Vect_J=Vect_M=Vect_X=Vect_A= NULL for(i in 1:length(d1)){ jours = seq(d1[i],d2[i],length=7) mois = as.POSIXlt(jours)$mon+1 annees = as.POSIXlt(jours)$year+1900 donnees = rep(X[i],7) Vect_J = c(Vect_J,jours) Vect_M = c(Vect_M,mois) Vect_A = c(Vect_A,annees) Vect_X = c(Vect_X,donnees) } base=data.frame(J=Vect_J,M=Vect_M, A=Vect_A,X=Vect_X) head(base) base$AM = base$A*100+base$M head(base) Y=tapply(base$X,as.factor(base$AM),mean) Z=ts(as.numeric(Y[1:144]), start=c(2004,1),frequency=12) plot(Z)
On peut superposer les deux d’ailleurs (il y a peut être un léger décalage sur la série hebdomadaire)
plot(X_h,col="blue") lines(as.numeric(time(Z)),as.numeric(Z), col="red",lwd=2)
Cours de Séries Temporelles
Le cours de séries temporelles commence également cette semaine. Je mets en ligne quelques notes de cours. Sinon, histoire d’illustrer un peu, quelques données extraites de google.fr/trends/ (je mettrais en ligne des données au fur et à mesure), sur le mot clé fièvre, chocolat, ou encore syllabus.
Vector Autoregressive Models
Consider here some model,
We’ve seen in class that stationnarity of that time series, in the sense that and , was valid if the roots (in ) of the characteristic polyonomial – – were outside the unit circle.
To visualize this point, consider the following time series
To generate that time series, we need to generate a bivariate white noise, i.e. (not necessarily a diagonal matrix), and . For instance
> n=500 > r=0.7 > set.seed(1) > Z1=rnorm(n) > Z2=rnorm(n) > E1=Z1 > E2=r*Z1+sqrt(1-r^2)*Z2
To generate now our time series, use
> A=matrix(c(.7,.2,.4,.3),2,2) > X1=X2=rep(0,n) > for(t in 2:n){ + X1[t]=A[1,1]*X1[t-1]+A[1,2]*X2[t-1]+E1[t] + X2[t]=A[2,1]*X1[t-1]+A[2,2]*X2[t-1]+E2[t] + }
Here, we have
> plot(X1,type="l",col="red") > lines(X2,col="blue")
Those two time series seem to be stationnary. And, indeed,
> polyroot(c(1,-sum(diag(A)),det(A))) [1] 1.18+0i 6.51-0i > Mod(polyroot(c(1,-sum(diag(A)),det(A)))) [1] 1.18 6.51
Forecast, Automatic Routines vs. Experience
This morning, in our Time Series course, we’ve been playing with some data I got from google.ca/trends/. Actually, we’ve been playing on some old version, downloaded 18 months ago (discussed in a previous post, in French).
> urls = "http://freakonometrics.free.fr/report-headphones-2015.csv" > report=read.table( + urls,skip=4,header=TRUE,sep=",",nrows=585) > tail(report) Semaine headphones 580 2015-02-08 - 2015-02-14 53 581 2015-02-15 - 2015-02-21 52 582 2015-02-22 - 2015-02-28 51 583 2015-03-01 - 2015-03-07 50 584 2015-03-08 - 2015-03-14 49 585 2015-03-15 - 2015-03-21 49
If we plot that weekly time series, we have
> plot(report[,2],type="l")
Working with weekly series is more complicated (at least to find a simple model, with only a few lags), so let us convert that series into a monthly one,
> source( + "http://freakonometrics.blog.free.fr/public/code/H2M.R") > headphones=H2M(report,lang="FR",type="ts") > plot(headphones)
Continue reading Forecast, Automatic Routines vs. Experience
Mensualiser une série hebdomadaire
Pour le devoir de série temporelles, les données fournies par Google trend sont hebdomadaires, ce qui peut rendre la modélisation compliquée. Comme on l’a évoqué en cours, il peut être plus simple de travailler sur des données mensuelles. La petite fonction suivante permet de transformer les données pour avoir des données mensuelles (avec des moyennes par mois, ce qui fait qu’un mois de 28 jours et un mois de 31 jours sont comparables). Histoire d’illustrer, prenons un mot au hasard, disons…. épilation. On commence par sauver le fichier csv, et on le lit sous R,
EPILATION=read.table("/home/charpentier/report-epilation.csv", skip=4,header=TRUE,sep=",",nrows=426)
La petite fonction suivant va nous aider à convertir la base en une série temporelle mensuelle,
H2M=function(BASE){ X=BASE[,2] date1=substr(as.character(BASE$Semaine),1,10) date2=substr(as.character(BASE$Semaine),14,23) D1=as.Date(date1,"%Y-%m-%d") D2=as.Date(date2,"%Y-%m-%d") vm=vy=N=NA for(t in 1:length(D1)){ mois=seq(D1[t],D2[t],length=7) vm=c(vm,as.POSIXlt(mois)$mon+1) vy=c(vy,as.POSIXlt(mois)$year+1900) N=c(N,rep(X[t],7))} N=N[-1]; vm=vm[-1]; vy=vy[-1] YM=vy*100+vm Z=tapply(N,as.factor(YM),mean) Zts=ts(Z,start=c(2004,1),frequency=12) return(Zts)}
Si on travaille sur la série hebdomadaire, on a la série suivante
hebdo=ts(EPILATION$épilation,start=2004, frequency=52)
La fonction d’autocorrélation est alors
acf(hebdo,160)
Maintenant, on peut travailler sur les données mensuelles. On utilise alors
mensuel=H2M(EPILATION)
Le graphique est alors le suivant
La fonction d’autocorrélation est cette fois la suivante
acf(mensuel,40)
On retrouve le comportement cyclique, avec une saisonnalité annuelle.
Séries Temporelles, références et exercices
Ce semestre, je vais donner le cours de Séries Temporelles du Master Statistique & Économétrie. Le plan de cours sera, en gros
- Concepts généraux, définition, stationnarité, processus Gaussien, propriété de Markov
- Opérateurs Retards
- Notions de lissage exponentiel
- Modèles Linéaires Stationnaires univariés AR et MA
- Modèles Linéaires Non-Stationnaires univariées, ARIMA et racines unités
- Modèles Linéaires Multivariées, VAR et co-intégration
- Modèles Linéaires univariés saisonniers
- Modèles Non-Linéaires, ARCH et GARCH
Parmi les références utiles:
- Brockwell & Davis Introduction to Time Series and Forecasting
- Brockwell & Davis Time Series: Theory and Methods
- Charpentier Séries Temporelles
- Coglan Using R for Time Series Analysis
- Cryer & Chan Time Series Analysis: With Applications in R
- Ghysels & Osborn Econometric Analysis of Seasonal Time Series
- Hyndman, Koehler, Ord & Snyder Forecasting with Exponential Smoothing
- Lütkepohl New Introduction to Multiple Time Series Analysis
- Shumway & Stoffer Time Series Analysis and Its Applications: With R Examples
- Tsay Multivariate Time Series Analysis with R and Financial Applications
- Zivot & Wang Modelling Financial Time Series with S+
Je peux aussi renvoyer vers le Task Views, de R dédié aux Séries temporelles, afin ‘avoir des compléments d’informations sur les packages de R. Je mettrais d’ailleurs en ligne des billets au fur et à mesure. Je mets aussi en ligne quelques séries d’exercices. Pour les premières données avec lesquelles on jouera un peu,
> autoroute=read.table( "http://freakonometrics.blog.free.fr/public/data/autoroute.csv",header=TRUE,sep=";")
(données de fréquentation d’autoroutes, en France).