Medie mobili (in C++)
La funzione vettorializzata per la media mobile, rollmean3(), aveva buone prestazioni ma una leggibilità molto scarsa. È davvero difficile capire che questo codice calcola una media mobile, il che rende la funzione più difficile da fare debug e da mantenere.
La seconda versione, rollmean2(), era più lenta ma più facile da leggere. Se la traduciamo in C++, auspicabilmente otterremo sia una buona leggibilità sia prestazioni elevate.
rollmean2() è definita nel tuo workspace; puoi stamparne la definizione per ricordarti come funziona. Ora tradurrai rollmean2() in C++, assegnandola a rollmean4().
Questo esercizio fa parte del corso
Ottimizzare il codice R con Rcpp
Istruzioni dell'esercizio
- Imposta
rescomeNumericVectordi lunghezzane con valori restituiti dal metodoget_na()diNumericVector. - Calcola
totalcome la somma dei primiwindowvalori dix. - Calcola la media in
window - 1come il totale diviso per l'ampiezza della finestra. - Nel secondo ciclo, aggiorna il totale sottraendo l'elemento
i - window-esimo dixe aggiungendo l'elementoi-esimo dix.
Esercizio pratico interattivo
Prova a risolvere questo esercizio completando il codice di esempio.
#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
)
*/