ÎncepețiÎncepe gratuit

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

Vezi cursul

Instrucțiuni pentru exercițiu

  • Definește res ca un NumericVector cu lungimea n și valorile date de metoda get_na() a clasei NumericVector.
  • Calculează total ca suma primelor window valori din x.
  • Calculează media la poziția window - 1 ca totalul împărțit la lățimea ferestrei.
  • În al doilea ciclu, actualizează totalul scăzând al i - window-lea element din x și adăugând al i-lea element din x.

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
   )   
*/
Editează și rulează codul