Kom igångKom igång gratis

Rullande medelvärden (i C++)

Den vektoriserade funktionen för rullande medelvärde, rollmean3(), hade god prestanda men mycket svag läsbarhet. Det är verkligen svårt att se att koden beräknar ett rullande medelvärde, vilket gör funktionen svårare att felsöka och underhålla.

Den andra versionen, rollmean2(), var långsammare men enklare att läsa. Om vi översätter den till C++ bör vi förhoppningsvis få både god läsbarhet och snabb prestanda.

rollmean2() är definierad i din arbetsmiljö – du kan skriva ut dess definition för att påminna dig om hur den fungerar. Du ska nu översätta rollmean2() till C++ och tilldela resultatet till rollmean4().

Den här övningen är en del av kursen

Optimera R-kod med Rcpp

Visa kurs

Övningsinstruktioner

  • Sätt res som en NumericVector med längden n och värden givna av NumericVector-metodens get_na().
  • Beräkna total som summan av de första window värdena i x.
  • Beräkna medelvärdet vid window - 1 som totalen dividerad med fönstrets bredd.
  • I den andra slingan uppdaterar du totalen genom att subtrahera det i - windowte elementet i x och addera det ite elementet i x.

Interaktiv övning med praktiskt arbete

Testa den här övningen genom att slutföra den här exempelkoden.

#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
   )   
*/
Redigera och kör kod