Medii mobile (în C++)
Funcția vectorizată pentru media mobilă, rollmean3(), avea performanțe bune, dar o lizibilitate foarte scăzută. Este greu de dedus că acest cod calculează o medie mobilă, ceea ce face funcția mai dificil de depanat și de întreținut.
A doua variantă, rollmean2(), era mai lentă, dar mai ușor de citit. Dacă o traducem în C++, sperăm să obținem atât lizibilitate, cât și performanță ridicată.
rollmean2() este definită în spațiul tău de lucru; poți afișa definiția ei pentru a-ți reaminti cum funcționează. Acum vei traduce rollmean2() în C++, atribuind rezultatul lui rollmean4().
Acest exercițiu face parte din cursul
Optimizarea codului R cu Rcpp
Instrucțiuni pentru exercițiu
- Definește
resca unNumericVectorcu lungimeanși valorile date de metodaget_na()a claseiNumericVector. - Calculează
totalca suma primelorwindowvalori dinx. - Calculează media la poziția
window - 1ca totalul împărțit la lățimea ferestrei. - În al doilea ciclu, actualizează totalul scăzând al
i - window-lea element dinxși adăugând ali-lea element dinx.
Exercițiu interactiv practic
Încearcă acest exercițiu completând acest cod de exemplu.
#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
)
*/