CommencezCommencez gratuitement

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

Voir le cours

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
  )
}
Modifier et exécuter le code