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
Instructions
- Définissez
rescomme unNumericVectorde longueurndont les valeurs sont données par la méthodeget_na()deNumericVector. - Calculez
totalcomme la somme deswindowpremières valeurs dex. - Calculez la moyenne à l’indice
window - 1comme 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 - windowdexet en ajoutant l’élémentidex.
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
)
*/