Moyennes roulantes (en C++)
La fonction vectorisée de moyenne roulante, rollmean3(), offrait une bonne performance mais une très faible lisibilité. On voit difficilement que ce code calcule une moyenne roulante, ce qui rend la fonction plus difficile à déboguer et à maintenir.
La deuxième version, rollmean2(), était plus lente mais plus facile à lire. Si nous la traduisons en C++, nous espérons obtenir à la fois une bonne lisibilité et une exécution rapide.
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().
Cette activité fait partie du cours
Optimiser le code R avec Rcpp
Instructions de l’exercice
- 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 à
window - 1comme le total divisé par la largeur de la fenêtre. - Dans la deuxième boucle, mettez à jour le total en soustrayant le
i - windowe élément dexet en ajoutant leie élément dex.
Exercice interactif pratique
Essayez cet exercice en complétant ce code d’exemple.
#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
)
*/