LoslegenKostenlos loslegen

Gleitende Mittelwerte (in C++)

Die Vektorvariante der Funktion für gleitende Mittelwerte, rollmean3(), war zwar performant, aber kaum lesbar. Es ist wirklich schwer zu erkennen, dass dieser Code einen gleitenden Mittelwert berechnet – das erschwert sowohl das Debuggen als auch die Pflege.

Die zweite Version, rollmean2(), war langsamer, aber leichter zu lesen. Wenn wir sie nach C++ übersetzen, bekommen wir hoffentlich gute Lesbarkeit und schnelle Ausführung.

rollmean2() ist in deinem Workspace definiert; du kannst dir die Definition ausgeben lassen, um dich an die Funktionsweise zu erinnern. Jetzt übersetzt du rollmean2() nach C++ und weist sie rollmean4() zu.

Diese Übung ist Teil des Kurses

R-Code mit Rcpp optimieren

Kurs anzeigen

Anleitung zur Übung

  • Setze res als NumericVector mit Länge n und Werten, die durch die Methode get_na() des NumericVector vorgegeben sind.
  • Berechne total als Summe der ersten window Werte von x.
  • Berechne den Mittelwert an Position window - 1 als total geteilt durch die Breite des Fensters.
  • Aktualisiere im zweiten Loop total, indem du das i - window-te Element von x abziehst und das i-te Element von x hinzufügst.

Interaktive Übung

Vervollständige den Beispielcode, um diese Übung erfolgreich abzuschließen.

#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
   )   
*/
Code bearbeiten und ausführen