Moyennes glissantes
Les moyennes glissantes (parfois appelées moyennes mobiles) sont utilisées en analyse de séries temporelles pour lisser le bruit. La valeur à chaque instant est remplacée par la moyenne des valeurs des instants proches (la fenêtre).
Une manière naturelle d’écrire cette fonction est
rollmean1 <- function(x, window = 3) {
n <- length(x)
res <- rep(NA, n)
for(i in seq(window, n)) {
res[i] <- mean(x[seq(i - window + 1, i)])
}
res
}
Cela appelle mean() de nombreuses fois, ce qui est inefficace. Une solution consiste à utiliser une variable total afin qu’à chaque itération de la boucle vous retiriez l’élément dont vous n’avez plus besoin et ajoutiez le nouveau.
rollmean2 <- function(x, window = 3){
n <- length(x)
res <- rep(NA, n)
total <- sum(head(x, window))
res[window] <- total / window
for(i in seq(window + 1, n)) {
total <- total + x[i] - x[i - window]
res[i] <- total / window
}
res
}
Dans tous les cas, il est beaucoup plus naturel d’écrire du code avec des boucles que du code vectorisé, ce qui peut réduire les performances. Les deux versions ci‑dessus sont inefficaces à leur manière. Avant de passer à la version C++ dans l’exercice suivant, écrivons une version utilisant la vectorisation. rollmean1(), rollmean2() et un vecteur aléatoire, x, sont disponibles dans votre espace de travail. Vous allez maintenant compléter la définition de la fonction rollmean3() et comparer les performances de ces fonctions.
Cet exercice fait partie du cours
Optimiser du code R avec Rcpp
Exercice interactif pratique
Essayez cet exercice en complétant cet exemple de code.
# Complete the definition of rollmean3()
rollmean3 <- function(x, window = 3) {
# Add the first window elements of x
initial_total <- ___(head(x, window))
# The elements to add at each iteration
lasts <- tail(x, - window)
# The elements to remove
firsts <- head(x, - window)
# Take the initial total and add the
# cumulative sum of lasts minus firsts
other_totals <- ___ + ___(___ - firsts)
# Build the output vector
c(
rep(NA, window - 1), # leading NA
initial_total / ___, # initial mean
other_totals / ___ # other means
)
}