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
Pokyny k cvičení
- Nastav
resjakoNumericVectors délkouna hodnotami získanými metodouget_na()třídyNumericVector. - Vypočítej
totaljako součet prvníchwindowhodnot vektorux. - Vypočítej průměr na pozici
window - 1jakototalvydělený šířkou okna. - Ve druhém cyklu aktualizuj
totalodečteními - window-tého prvku vektoruxa přičteními-tého prvku vektorux.
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
)
*/