Začněte nyníZačněte zdarma

Klouzavé průměry (v C++)

Vektorizovaná funkce pro výpočet klouzavého průměru rollmean3() vykazovala skvělý výkon, ale velmi slabou čitelnost. Kód vůbec neprozrazuje, že počítá klouzavý průměr, což funkci ztěžuje ladění i údržbu.

Druhá verze, rollmean2(), byla sice pomalejší, ale čitelnější. Pokud ji přepíšeme do C++, měli bychom získat přehledný kód i rychlý výkon zároveň.

rollmean2() je definována v tvém pracovním prostředí – její definici si můžeš vypsat, abys osvěžil/a, jak funguje. Teď ji přepiš do C++ a výsledek ulož jako rollmean4().

Toto cvičení je součástí kurzu

Optimizing R Code with Rcpp

Zobrazit kurz

Pokyny k cvičení

  • Nastav res jako NumericVector s délkou n a hodnotami získanými metodou get_na() třídy NumericVector.
  • Vypočítej total jako součet prvních window hodnot vektoru x.
  • Vypočítej průměr na pozici window - 1 jako total vydělený šířkou okna.
  • Ve druhém cyklu aktualizuj total odečtením i - window-tého prvku vektoru x a přičtením i-tého prvku vektoru x.

Interaktivní cvičení na vyzkoušení si v praxi

Vyzkoušejte si toto cvičení dokončením tohoto ukázkového kódu.

#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
   )   
*/
Upravit a spustit kód