Formation - Désaisonnalisation avec JDemetra+ et RJDemetra
Auteur
Alain Quartier-la-Tente
L’objectif de ce TP est d’apprendre à manipuler les séries temporelles sous R en utilisant les packages de bases.
Dans R il existe de nombreux packages qui permettent de manipuler les séries temporelles. Pour n’en citer que quelques-uns :
- Les objets ts peuvent être créés à partir du package stats ;
- Les objets zoo peuvent être créés à partir du package zoo ;
- Les objets xts peuvent être créés à partir du package xts ;
- Les objets tis peuvent être créés à partir du package tseries ;
- Les objets tsibble peuvent être créés à partir du package tsibble.
tsbox permet quand à lui de facilement passer d’une classe à l’autre.
Ici nous nous concentrerons essentiellement sur les trois premiers : ts stocker les séries temporelles, zoo et xts pour effectuer certaines manipulations supplémentaires.
Manipulation des séries temporelles avec ts()
Création d’une série temporelle
La fonction ts() permet de créer des objets séries-temporelles à partir un vecteur (ou une matrice). La syntaxe de base est ts(vector, start=, end=, frequency=) où start et end sont la première et la dernière observation, frequency est le nombre d’observations par unité de temps (1=annuelle, 2=semestrielle, 4=trimestrielle, 6=bi-mestrielle, 12=mensuelle, etc.).
Par exemple pour créer une série trimestrielle ayant les valeurs de 1 à 10 et commençant en 1959Q2 :
ts(1:10, frequency =4, start =c(1959, 2)) # 2ème trimestre de 1959
Si l’on directement extraire un sous-ensemble de la série on peut spécifier les paramètres end et start. Par exemple pour ne garder que les valeurs jusqu’en 1960 inclus :
ts(1:10, frequency =4, start =c(1959, 2), end =c(1960, 4))
Qtr1 Qtr2 Qtr3 Qtr4
1959 1 2 3
1960 4 5 6 7
Ou alors utiliser la fonction window une fois l’objet créé :
ts_object <-ts(1:10, frequency =4, start =c(1959, 2))window(ts_object, end =c(1960, 4))
Qtr1 Qtr2 Qtr3 Qtr4
1959 1 2 3
1960 4 5 6 7
On peut récupérer les différents attributs avec les fonctions start(), end() et frequency() :
start(ts_object)
[1] 1959 2
end(ts_object)
[1] 1961 3
frequency(ts_object)
[1] 4
Deux autres fonctions peuvent aussi être utiles : time() crée un série-temporelle à partir des dates de notre série-temporelle et cycle() donne la position dans le cycle de chaque observation.
Et avec les même fonctions que pour les matrices on peut récupérer les noms des colonnes (colnames), le nombre de variables (ncol), etc.
Attention
Une source classique d’erreur est de manipuler des séries-temporelles uni et multivariées et de vouloir utiliser les fonctions liées aux matrices sur les séries univariées. Par exemple, colnames(ts_object) renverra toujours l’objet NULL. Une solution est de tester si l’objet est multivarié avec la fonction is.mts().
Manipulation basiques
Pour concaténer plusieurs séries temporelles, les fonctions deux fonctions suivantes peuvent ts.union() et ts.intersect().
ts_object2 <-ts(1:10, frequency =4, start =c(1960, 1))ts.union(ts_object, ts_object2) # on garde toute la couverture temporelle en rajoutant des NA
ts_object ts_object2
1959 Q2 1 NA
1959 Q3 2 NA
1959 Q4 3 NA
1960 Q1 4 1
1960 Q2 5 2
1960 Q3 6 3
1960 Q4 7 4
1961 Q1 8 5
1961 Q2 9 6
1961 Q3 10 7
1961 Q4 NA 8
1962 Q1 NA 9
1962 Q2 NA 10
ts.intersect(ts_object, ts_object2) # on ne garde que les périodes communes
Pour calculer la série retardée/avancée, il suffit d’utiliser la fonction lag() :
# série retardée d'un mois : en février 2010 on a la valeur de janvier 2010lag(ipi_fr_manuf, k =-1)
La fonction diff permet de calculer la différence entre deux périodes
diff(ipi_fr_manuf, k =1)
Exercice
Écrire une fonction ev() qui calcule l’évolution mensuelle si la série en entrée est mensuelle, l’évolution trimestrielle si la série en entrée est trimestrielle, etc.
Solution
ev <-function(x){ result <- (x/lag(x, k =-1) -1) *100return(result)}# Ou de manière équivalente :ev2 <-function(x){# Attention ici c'est bien k = 1 dans la fonction diff# et k = -1 dans la fonction lag result <- (diff(x, k =1) /lag(x, k =-1)) *100return(result)}################################################## Remarque : pour des raisons informatiques ces deux fonctions ne donnent pas exactement# le même résultat. C'est un problème récurrent lorsque l'on# souhaite tester l'égalité entre deux séries temporelles :all (ev(ipi_fr_manuf) ==ev2(ipi_fr_manuf))
[1] FALSE
# Une solution est plutôt d'utiliser la fonction all.equal():isTRUE(all.equal(ev(ipi_fr_manuf), ev2(ipi_fr_manuf)))
[1] TRUE
Utilisation de xts et zoo
Utilisation de xts
Un des avantages du package xts est qu’il permet d’appliquer une fonction à chaque période d’une série temporelle (par exemple à toutes les données trimestrielles, annuelles, etc.). Il s’agit des fonctions apply.monthly(), apply.quarterly(), apply.yearly(), etc. Pour cela il faut auparavant convertir les données au format xts.
Calculer l’évolution trimestrielle de ipi_fr_manuf.
Solution
# Tout d'abord on prolonge l'IPI par des valeurs manquantes jusqu'à la fin # de l'année, sinon la dernière somme sur le trimestre est fausse.ipi_fr_manuf_prolonge <-window(ipi_fr_manuf, end =c(2019, 12), extend =TRUE)somme_trim <-apply.quarterly(as.xts(ipi_fr_manuf_prolonge), sum)# Attention la fonction lag n'agit pas pareil pour les objets xts et ts :# il faut ici utiliser l'option k = 1evol_trim <- (somme_trim/lag(somme_trim, k =1) -1) *100# On peut utiliser la fonction format() # si l'on veut convertir automatiquement en un objet tsstart_year <-as.numeric(format(start(evol_trim), "%Y"))start_quarter <-as.numeric(substr(quarters(start(evol_trim)), 2, 2))ts(evol_trim, start =c(start_year, start_quarter), frequency =4)
Le package zoo donne un ensemble d’outils qui permettent de manipuler les séries-temporelles. De nombreux packages (dont xts) sont d’ailleurs basés sur ce format. Il permet notamment de faire des imputations de données manquantes selon différentes fonctions (toutes les fonctions commençant par na.) et de mieux gérer le format des dates associées aux séries temporelles (ce qui permet de faire des manipulations avec la fonction format, ce qui permet par exemple plus facilement exporter des séries temporelles sous Excel). Le calcul de l’évolution trimestrielle aurait par exemple pu être faite avec ce package :
somme_trim <-aggregate(as.zoo(ipi_fr_manuf_prolonge), yearqtr, sum)somme_trim <-as.ts(somme_trim) #La conversion en ts est plus simple depuis un objet zooevol_trim <-ev(somme_trim)evol_trim
Sur la série serie_avec_NA, utiliser les différentes fonctions du package zoo pour : 1. Enlever les valeurs manquantes au début de la série ; 2. Remplacer les valeurs manquantes à la fin de la série par la dernière valeur observée. 3. Interpoler de manière linéaire les valeurs manquantes entre les 0 et les 1.
Indice
Les trois fonctions à utiliser sont : na.trim(), na.locf et na.approx()
Solution
# D'abord on enlève les valeurs manquantes au début de la sérieetape_1 <-na.trim(serie_avec_NA, sides ="left")etape_1
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
2001 0 0 0 0 0 0 0 0 0 0 0 0
2002 0 0 0 0 0 0 0 0 0 0 0 0
2003 NA NA NA NA NA NA NA NA NA NA NA NA
2004 NA NA NA NA NA NA NA NA NA NA NA NA
2005 1 1 1 1 1 1 1 1 1 1 1 1
2006 1 1 1 1 1 1 1 1 1 1 1 1
2007 NA NA NA NA NA NA NA NA NA NA NA NA
# Ensuite on interpoleetape_2 <-na.approx(etape_1, na.rm =FALSE)etape_2
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
2001 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
2002 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
2003 0.04 0.08 0.12 0.16 0.20 0.24 0.28 0.32 0.36 0.40 0.44 0.48
2004 0.52 0.56 0.60 0.64 0.68 0.72 0.76 0.80 0.84 0.88 0.92 0.96
2005 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
2006 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
2007 NA NA NA NA NA NA NA NA NA NA NA NA
# Enfin on remplace les valeurs à la fin de la sérieetape_3 <-na.locf(etape_2)etape_3
À l’aide des fonctions as.yearmon() et format(), créer un data.frame contenant une colonne “date” qui contient les dates au format JJ/MM/YYYY et une deuxième colonnes avec les valeurs de ipi_fr_manuf.
Indice
La fonction as.yearmon() doit être appliquée sur time(ipi_fr_manuf). Pour la fonction format regarder l’aide ?format.Date.
Il peut également être utile d’exporter un objet R ts ou mts vers un fichier Excel, tout en rajoutant une colonne “date” qui sera au format date. Ci-dessous un exemple en utilisant le package XLConnect :
library(XLConnect)ts2xls <-function(x, file, sheet="Feuille 1", format ="dd/mm/yyyy"){ wb <-loadWorkbook(file, create =TRUE)createSheet(wb, sheet)if(is.mts(x)){ col <-c("date", colnames(x)) }else{ col <-c("date", "x") }# Le titrewriteWorksheet(wb,matrix(col,nrow =1),sheet = sheet,startCol =1,startRow =1,header =FALSE)# Petit trick pour que la colonne date soit au format date d'Excel csDate <-getOrCreateCellStyle(wb, name ="date")setDataFormat(csDate, format = format) date <-as.Date(format(zoo::as.Date((time(x))), "%d/%m/%Y"),"%d/%m/%Y")writeWorksheet(wb,date,sheet = sheet,startCol =1,startRow =2,header =FALSE)setCellStyle(wb, sheet = sheet, row =seq_along(date)+1,col =1,cellstyle = csDate)# Fin colonne date# Autres colonneswriteWorksheet(wb,x,sheet = sheet,startCol =2,startRow =2,header =FALSE)setColumnWidth(wb, sheet, column =seq_along(col), width =-1)saveWorkbook(wb, file)}