Moyennes mobiles
Les moyennes mobiles (parfois appelées moyennes glissantes) sont utilisées en analyse de séries chronologiques pour atténuer le bruit. La valeur à chaque point dans le temps est remplacée par la moyenne des valeurs aux points voisins (la « fenêtre »).
Une façon 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
}
Cette approche 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 devenu inutile 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 souvent plus naturel d'écrire du code avec des boucles que du code vectorisé, ce qui peut réduire la performance. Les deux versions ci‑dessus sont inefficaces à leur manière. Avant de faire la version en C++ dans le prochain exercice, écrivons une version qui utilise 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 évaluer la performance de ces fonctions.
Cette activité fait partie du cours
Optimiser le code R avec Rcpp
Exercice interactif pratique
Essayez cet exercice en complétant ce code d’exemple.
# 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
)
}