CommencerCommencer gratuitement

Moyennes glissantes (en C++)

La fonction vectorisée de moyenne glissante, rollmean3(), offrait de bonnes performances mais une lisibilité très médiocre. Il est vraiment difficile de voir que ce code calcule une moyenne glissante, ce qui rend la fonction plus difficile à déboguer et à maintenir.

La deuxième version, rollmean2(), était plus lente mais plus lisible. Si nous la traduisons en C++, nous devrions obtenir une bonne lisibilité et des performances élevées.

rollmean2() est définie dans votre espace de travail ; vous pouvez afficher sa définition pour vous rappeler son fonctionnement. Vous allez maintenant traduire rollmean2() en C++ et l’assigner à rollmean4().

Cet exercice fait partie du cours

Optimiser du code R avec Rcpp

Afficher le cours

Instructions

  • Définissez res comme un NumericVector de longueur n dont les valeurs sont données par la méthode get_na() de NumericVector.
  • Calculez total comme la somme des window premières valeurs de x.
  • Calculez la moyenne à l’indice window - 1 comme le total divisé par la largeur de la fenêtre.
  • Dans la deuxième boucle, mettez à jour le total en soustrayant l’élément i - window de x et en ajoutant l’élément i de x.

Exercice interactif pratique

Essayez cet exercice en complétant cet exemple de code.

#include 
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector rollmean4(NumericVector x, int window) {
  int n = x.size();
  
  // Set res as a NumericVector of NAs with length n
  NumericVector res(___, ___::___());
  
  // Sum the first window worth of values of x
  double total = 0.0;
  for(int i = 0; i < window; i++) {
    total += ___;
  }
  
  // Treat the first case seperately
  res[window - 1] = ___ / window;
  
  // Iteratively update the total and recalculate the mean 
  for(int i = window; i < n; i++) {
    // Remove the (i - window)th case, and add the ith case
    total += - ___ + ___;
    // Calculate the mean at the ith position
    res[i] = total / window;
  }
  
  return res;  
}

/*** R
   # Compare rollmean2, rollmean3 and rollmean4   
   set.seed(42)
   x <- rnorm(1e4)
   microbenchmark( 
    rollmean2(x, 4), 
    rollmean3(x, 4), 
    rollmean4(x, 4), 
    times = 5
   )   
*/
Modifier et exécuter le code