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
Övningsinstruktioner
- Sätt
ressom enNumericVectormed längdennoch värden givna avNumericVector-metodensget_na(). - Beräkna
totalsom summan av de förstawindowvärdena ix. - Beräkna medelvärdet vid
window - 1som totalen dividerad med fönstrets bredd. - I den andra slingan uppdaterar du totalen genom att subtrahera det
i - windowte elementet ixoch addera detite elementet ix.
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
)
*/