0 - Traitement des séries temporelles sous

Désaisonnaliser une série temporelle

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.

Les packages suivants seront utilisés :

packages_to_install <- c("zoo", "xts", "dplyr", "XLConnect", "remotes")

packages <- packages_to_install[! packages_to_install %in% installed.packages()[,"Package"]]
if (length(packages) > 0) {
    install.packages(packages)
}
if (! "rjd3toolkit" %in% installed.packages()[,"Package"])
    remotes::install_github("rjdemetra/rjd3toolkit")

1 Manipulation des séries temporelles avec ts()

1.1 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=)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
     Qtr1 Qtr2 Qtr3 Qtr4
1959         1    2    3
1960    4    5    6    7
1961    8    9   10     
# Équivalent à 
ts(1:10, frequency = 4, start = 1959 + 1/4)
     Qtr1 Qtr2 Qtr3 Qtr4
1959         1    2    3
1960    4    5    6    7
1961    8    9   10     

On peut aussi définir l’objet à partir de sa date de fin :

ts(1:10, frequency = 4, end = c(1959, 2))
     Qtr1 Qtr2 Qtr3 Qtr4
1957    1    2    3    4
1958    5    6    7    8
1959    9   10          

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.

time(ts_object)
        Qtr1    Qtr2    Qtr3    Qtr4
1959         1959.25 1959.50 1959.75
1960 1960.00 1960.25 1960.50 1960.75
1961 1961.00 1961.25 1961.50        
cycle(ts_object)
     Qtr1 Qtr2 Qtr3 Qtr4
1959         2    3    4
1960    1    2    3    4
1961    1    2    3     
Exercice

Extraire toutes les données du 2ème trimestre de l’objet ts_object

ts_object[cycle(ts_object) == 2]
[1] 1 5 9

Autre option : utiliser la fonction window()

window(ts_object, frequency = 1)
Time Series:
Start = 1959.25 
End = 1961.25 
Frequency = 1 
[1] 1 5 9

Explication : lorsque l’on spécifie le paramètre frequency dans la fonction window(), on change la fréquence de la série. Dans notre cas, on veut extraire les valeurs du deuxième trimestre : on veut donc une série annuelle qui contient toutes les valeurs des deuxièmes trimestres. La première observation de ts_object étant un deuxième trimestre, cela donne ce que l’on veut. Pour extraire les valeurs des troisièmes trimestres il faut en plus changer la date de début :

window(ts_object, start = c(1950, 3), frequency = 1)
Time Series:
Start = 1959.25 
End = 1961.25 
Frequency = 1 
[1] 1 5 9
Exercice

Créer une série temporelle mensuelle qui commence en 2000, qui se termine en janvier 2020, qui vaut 1 en avril 2009 et 0 à toutes les autres dates.

Option 1 : utiliser la fonction window()

indicatrice <- ts(0, start = 2000, end = 2020, frequency = 12)
window(indicatrice, start = c(2009, 4), end = c(2009, 4)) <- 1
indicatrice
     Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
2000   0   0   0   0   0   0   0   0   0   0   0   0
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   0   0   0   0   0   0   0   0   0   0   0   0
2004   0   0   0   0   0   0   0   0   0   0   0   0
2005   0   0   0   0   0   0   0   0   0   0   0   0
2006   0   0   0   0   0   0   0   0   0   0   0   0
2007   0   0   0   0   0   0   0   0   0   0   0   0
2008   0   0   0   0   0   0   0   0   0   0   0   0
2009   0   0   0   1   0   0   0   0   0   0   0   0
2010   0   0   0   0   0   0   0   0   0   0   0   0
2011   0   0   0   0   0   0   0   0   0   0   0   0
2012   0   0   0   0   0   0   0   0   0   0   0   0
2013   0   0   0   0   0   0   0   0   0   0   0   0
2014   0   0   0   0   0   0   0   0   0   0   0   0
2015   0   0   0   0   0   0   0   0   0   0   0   0
2016   0   0   0   0   0   0   0   0   0   0   0   0
2017   0   0   0   0   0   0   0   0   0   0   0   0
2018   0   0   0   0   0   0   0   0   0   0   0   0
2019   0   0   0   0   0   0   0   0   0   0   0   0
2020   0                                            

Option 2 : utiliser time()

indicatrice <- ts(0, start = 2000, end = 2020, frequency = 12)
# Donne un vecteur de booléens
(time(indicatrice) == 2009 + 3/12) 
       Jan   Feb   Mar   Apr   May   Jun   Jul   Aug   Sep   Oct   Nov   Dec
2000 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2001 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2002 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2003 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2004 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2005 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2006 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2007 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2008 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2009 FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2010 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2011 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2012 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2013 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2014 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2015 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2016 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2017 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2018 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2019 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2020 FALSE                                                                  
# on ajoute + 0 pour forcer la convertion en numérique
(time(indicatrice) == 2009 + 3/12) + 0
     Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
2000   0   0   0   0   0   0   0   0   0   0   0   0
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   0   0   0   0   0   0   0   0   0   0   0   0
2004   0   0   0   0   0   0   0   0   0   0   0   0
2005   0   0   0   0   0   0   0   0   0   0   0   0
2006   0   0   0   0   0   0   0   0   0   0   0   0
2007   0   0   0   0   0   0   0   0   0   0   0   0
2008   0   0   0   0   0   0   0   0   0   0   0   0
2009   0   0   0   1   0   0   0   0   0   0   0   0
2010   0   0   0   0   0   0   0   0   0   0   0   0
2011   0   0   0   0   0   0   0   0   0   0   0   0
2012   0   0   0   0   0   0   0   0   0   0   0   0
2013   0   0   0   0   0   0   0   0   0   0   0   0
2014   0   0   0   0   0   0   0   0   0   0   0   0
2015   0   0   0   0   0   0   0   0   0   0   0   0
2016   0   0   0   0   0   0   0   0   0   0   0   0
2017   0   0   0   0   0   0   0   0   0   0   0   0
2018   0   0   0   0   0   0   0   0   0   0   0   0
2019   0   0   0   0   0   0   0   0   0   0   0   0
2020   0                                            

Pour tracer un graphique il suffit maintenant d’utiliser les fonctions plot() et lines()

plot(ts_object * 2)
lines(ts_object, col = "red")

1.2 Séries multivariées

De la même façon que précédemment on peut créer une série temporelle multivariée. Cette fois-ci l’objet créé est à la fois mts, ts et matrix

set.seed(1)
# On génère 300 observations d'une loi normale (0, 1)
loi_normale <- rnorm(300)
mts <- ts(matrix(loi_normale, nrow = 100, ncol = 3),
          start = c(1961, 1), frequency = 12)

On peut accéder à la première variable de la même façon que dans une matrice : par son nom ou son numéro de colonne :

colnames(mts)
[1] "Series 1" "Series 2" "Series 3"
# mts[,1] # ou de façon équivalente :
mts[, "Series 1"]
              Jan          Feb          Mar          Apr          May
1961 -0.626453811  0.183643324 -0.835628612  1.595280802  0.329507772
1962 -0.621240581 -2.214699887  1.124930918 -0.044933609 -0.016190263
1963  0.619825748 -0.056128740 -0.155795507 -1.470752384 -0.478150055
1964 -0.394289954 -0.059313397  1.100025372  0.763175748 -0.164523596
1965 -0.112346212  0.881107726  0.398105880 -0.612026393  0.341119691
1966  2.401617761 -0.039240003  0.689739362  0.028002159 -0.743273209
1967  0.610726353 -0.934097632 -1.253633400  0.291446236 -0.443291873
1968  0.593946188  0.332950371  1.063099837 -0.304183924  0.370018810
1969 -1.276592208 -0.573265414 -1.224612615 -0.473400636             
              Jun          Jul          Aug          Sep          Oct
1961 -0.820468384  0.487429052  0.738324705  0.575781352 -0.305388387
1962  0.943836211  0.821221195  0.593901321  0.918977372  0.782136301
1963  0.417941560  1.358679552 -0.102787727  0.387671612 -0.053805041
1964 -0.253361680  0.696963375  0.556663199 -0.688755695 -0.707495157
1965 -1.129363096  1.433023702  1.980399899 -0.367221476 -1.044134626
1966  0.188792300 -1.804958629  1.465554862  0.153253338  2.172611670
1967  0.001105352  0.074341324 -0.589520946 -0.568668733 -0.135178615
1968  0.267098791 -0.542520031  1.207867806  1.160402616  0.700213650
1969                                                                 
              Nov          Dec
1961  1.511781168  0.389843236
1962  0.074564983 -1.989351696
1963 -1.377059557 -0.414994563
1964  0.364581962  0.768532925
1965  0.569719627 -0.135054604
1966  0.475509529 -0.709946431
1967  1.178086997 -1.523566800
1968  1.586833455  0.558486426
1969                          

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

1.3 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
        ts_object ts_object2
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

On va maintenant utiliser la série d’indice de production industrielle de la France (CVS-CJO) :

ipi_fr_manuf <- ts(c(99, 99.4, 99.7, 99.4, 100.8, 100, 98.7, 100.2, 101.2, 
100.6, 99.9, 100.9, 102.4, 100.8, 99.5, 100.7, 99.8, 99.1, 99.8, 
101.6, 100.4, 99.4, 102.8, 101, 100.2, 101.1, 102.6, 101.8, 103.7, 
103, 103.6, 103.5, 104.4, 105.6, 105.5, 105.9, 103.6, 102.9, 
103.8, 103.8, 102.5, 104.2, 104, 104.6, 103.4, 104.2, 103.4, 
103.7, 104.9, 105.8, 104.4, 104.3, 106, 103.7, 104.1, 103.1, 
103.9, 104.4), start = 2015, frequency = 12)

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 2010
lag(ipi_fr_manuf, k = -1) 
       Jan   Feb   Mar   Apr   May   Jun   Jul   Aug   Sep   Oct   Nov   Dec
2015        99.0  99.4  99.7  99.4 100.8 100.0  98.7 100.2 101.2 100.6  99.9
2016 100.9 102.4 100.8  99.5 100.7  99.8  99.1  99.8 101.6 100.4  99.4 102.8
2017 101.0 100.2 101.1 102.6 101.8 103.7 103.0 103.6 103.5 104.4 105.6 105.5
2018 105.9 103.6 102.9 103.8 103.8 102.5 104.2 104.0 104.6 103.4 104.2 103.4
2019 103.7 104.9 105.8 104.4 104.3 106.0 103.7 104.1 103.1 103.9 104.4      

La fonction diff permet de calculer la différence entre deux périodes :

diff(ipi_fr_manuf, lag = 1)
      Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec
2015       0.4  0.3 -0.3  1.4 -0.8 -1.3  1.5  1.0 -0.6 -0.7  1.0
2016  1.5 -1.6 -1.3  1.2 -0.9 -0.7  0.7  1.8 -1.2 -1.0  3.4 -1.8
2017 -0.8  0.9  1.5 -0.8  1.9 -0.7  0.6 -0.1  0.9  1.2 -0.1  0.4
2018 -2.3 -0.7  0.9  0.0 -1.3  1.7 -0.2  0.6 -1.2  0.8 -0.8  0.3
2019  1.2  0.9 -1.4 -0.1  1.7 -2.3  0.4 -1.0  0.8  0.5          

En revanche, le paramètre lag ne peut prendre que une valeur. La fonction rjd3toolkit::differences() permet d’effectuer plusieurs différences et a également un paramètre mean pour centrer la série. Par exemple, pour effectuer à la fois une différenciation régulière et saisonnière (d’ordre 12) :

rjd3toolkit::differences(ipi_fr_manuf, lags = c(1, 12))
             Jan         Feb         Mar         Apr         May         Jun
2016             -1.92888889 -1.52888889  1.57111111 -2.22888889  0.17111111
2017 -2.22888889  2.57111111  2.87111111 -1.92888889  2.87111111  0.07111111
2018 -1.42888889 -1.52888889 -0.52888889  0.87111111 -3.12888889  2.47111111
2019  3.57111111  1.67111111 -2.22888889 -0.02888889  3.07111111 -3.92888889
             Jul         Aug         Sep         Oct         Nov         Dec
2016  2.07111111  0.37111111 -2.12888889 -0.32888889  4.17111111 -2.72888889
2017 -0.02888889 -1.82888889  2.17111111  2.27111111 -3.42888889  2.27111111
2018 -0.72888889  0.77111111 -2.02888889 -0.32888889 -0.62888889 -0.02888889
2019  0.67111111 -1.52888889  2.07111111 -0.22888889                        
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.

La fonction ev() transformera donc toute série \(X_t\) en : \[ Y_t=\frac{X_t-X_{t-1}}{ X_{t-1} }=\frac{X_t}{ X_{t-1} } - 1. \]

ev <- function(x){
  result <- (x/stats::lag(x, k = -1) - 1) * 100
  return(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, lag = 1) /lag(x, k = -1)) * 100
  return(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

2 Utilisation de xts et zoo

2.1 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.

Par exemple pour calculer la moyenne annuelle :

library(xts)
moy_an <- apply.yearly(as.xts(ipi_fr_manuf), mean)
moy_an
              [,1]
Dec 2015  99.98333
Dec 2016 100.60833
Dec 2017 103.40833
Dec 2018 103.67500
Oct 2019 104.46000
Exercice

Calculer l’évolution trimestrielle de ipi_fr_manuf.

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 = 1. Voir l’aide associée à ?lag.xts. Pour garder la même convention entre lag.ts() et lag.xts() on peut utiliser l’option options(xts.compat.zoo.lag=TRUE).

evol_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 ts :

start_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)
            Qtr1        Qtr2        Qtr3        Qtr4
2015          NA  0.70446159 -0.03331113  0.43318894
2016  0.43132050 -1.02411629  0.73431242  0.46388337
2017  0.23087071  1.51365581  0.97244733  1.76565008
2018 -2.11356467  0.06445375  0.48309179 -0.22435897
2019  1.22068744 -0.34909553 -0.92356688          NA

On peut aussi directement utiliser le package ts_box et la fonction ts_ts() :

tsbox::ts_ts(evol_trim)
            Qtr1        Qtr2        Qtr3        Qtr4
2015                      NA  0.70446159 -0.03331113
2016  0.43318894  0.43132050 -1.02411629  0.73431242
2017  0.46388337  0.23087071  1.51365581  0.97244733
2018  1.76565008 -2.11356467  0.06445375  0.48309179
2019 -0.22435897  1.22068744 -0.34909553 -0.92356688
2020          NA                                    

On aurait en fait pu le faire directement avec les fonctions de base R ! Par contre la situation aurait été plus compliquée avec des données haute fréquence (du type journalières) non correctement gérées par ts :

stats::aggregate.ts(ipi_fr_manuf, nfrequency = 4,
          FUN = mean)
          Qtr1      Qtr2      Qtr3      Qtr4
2015  99.36667 100.06667 100.03333 100.46667
2016 100.90000  99.86667 100.60000 101.06667
2017 101.30000 102.83333 103.83333 105.66667
2018 103.43333 103.50000 104.00000 103.76667
2019 105.03333 104.66667 103.70000          

Cette fonction fait ici une somme sur 4 périodes consécutives mais ne reconnait pas les différents mois des trimestres :

stats::aggregate.ts(window(ipi_fr_manuf, start = c(2015,2)), nfrequency = 4,
          FUN = mean)
Time Series:
Start = 2015.08333333333 
End = 2019.58333333333 
Frequency = 4 
 [1]  99.50000  99.83333 100.66667 101.06667 100.33333  99.56667 100.46667
 [8] 101.33333 101.83333 103.43333 104.50000 105.00000 103.50000 103.56667
[15] 104.06667 104.00000 104.83333 104.60000 103.80000

Une autre possibilité est d’utiliser la fonction rjd3toolkit::aggregate() (mais dont les fonctions d’agrégation sont limitées) :

rjd3toolkit::aggregate(window(ipi_fr_manuf, start = c(2015,2)),
                       nfreq = 4)
      Qtr1  Qtr2  Qtr3  Qtr4
2015       300.2 300.1 301.4
2016 302.7 299.6 301.8 303.2
2017 303.9 308.5 311.5 317.0
2018 310.3 310.5 312.0 311.3
2019 315.1 314.0 311.1      

2.2 Utilisation de zoo

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 zoo
evol_trim <- ev(somme_trim)
evol_trim
            Qtr1        Qtr2        Qtr3        Qtr4
2015              0.70446159 -0.03331113  0.43318894
2016  0.43132050 -1.02411629  0.73431242  0.46388337
2017  0.23087071  1.51365581  0.97244733  1.76565008
2018 -2.11356467  0.06445375  0.48309179 -0.22435897
2019  1.22068744 -0.34909553 -0.92356688          NA

Pour le prochain exercice, utiliser la série suivante :

serie_avec_NA <- ts(c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0, 0, 
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NA, 
  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
  NA, NA, NA, NA, NA, NA, NA, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, NA, NA, NA, NA, NA, NA, 
  NA, NA, NA, NA, NA, NA), start = 2000, frequency = 12)
Exercice

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.

Les trois fonctions à utiliser sont : na.trim(), na.locf() et na.approx(). Il faudra peut-être inverser deux étapes pour que cela marche.

D’abord on enlève les valeurs manquantes au début de la série

etape_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 interpole

etape_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érie

etape_3 <- na.locf(etape_2)
etape_3
      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 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
Exercice

À 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.

La fonction as.yearmon() doit être appliquée sur time(ipi_fr_manuf). Pour la fonction format regarder l’aide ?format.Date.

dates <- as.yearmon(time(ipi_fr_manuf))
dates <- format(dates, "%d/%m/%Y")
donnees_formatees <- data.frame(date = dates, ipi = ipi_fr_manuf)
head(donnees_formatees)
        date   ipi
1 01/01/2015  99.0
2 01/02/2015  99.4
3 01/03/2015  99.7
4 01/04/2015  99.4
5 01/05/2015 100.8
6 01/06/2015 100.0

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 titre
  writeWorksheet(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 colonnes
  writeWorksheet(wb,x,sheet = sheet,startCol = 2,startRow = 2,
                 header = FALSE)
  setColumnWidth(wb, sheet, column = seq_along(col), width = -1)
  saveWorkbook(wb, file)
}