Rollende gemiddelden
Rollende gemiddelden (ook wel moving averages genoemd) worden in tijdreeksanalyse gebruikt om ruis weg te nemen. De waarde op elk tijdstip wordt vervangen door het gemiddelde van de waarden in de buurt (het venster).
Een natuurlijke manier om deze functie te schrijven is
rollmean1 <- function(x, window = 3) {
n <- length(x)
res <- rep(NA, n)
for(i in seq(window, n)) {
res[i] <- mean(x[seq(i - window + 1, i)])
}
res
}
Deze roept mean() heel vaak aan, wat inefficiënt is. Eén oplossing is om een variabele total te gebruiken, zodat je bij elke iteratie van de lus het element dat je niet meer nodig hebt verwijdert en het nieuwe toevoegt.
rollmean2 <- function(x, window = 3){
n <- length(x)
res <- rep(NA, n)
total <- sum(head(x, window))
res[window] <- total / window
for(i in seq(window + 1, n)) {
total <- total + x[i] - x[i - window]
res[i] <- total / window
}
res
}
Hoe dan ook, het is veel natuurlijker om lus-code te schrijven dan gevectoriseerde code, maar dat kan de performance verminderen. Beide versies hierboven zijn op hun eigen manier inefficiënt. Voordat we in de volgende oefening de C++-versie doen, schrijven we eerst een versie die vectorisatie gebruikt. rollmean1(), rollmean2() en een willekeurige vector, x, zijn beschikbaar in je werkruimte. Je maakt nu de functiedefinitie van rollmean3() af en vergelijkt de performance van deze functies met een benchmark.
Deze oefening maakt deel uit van de cursus
R-code optimaliseren met Rcpp
Praktische interactieve oefening
Probeer deze oefening eens door deze voorbeeldcode in te vullen.
# Complete the definition of rollmean3()
rollmean3 <- function(x, window = 3) {
# Add the first window elements of x
initial_total <- ___(head(x, window))
# The elements to add at each iteration
lasts <- tail(x, - window)
# The elements to remove
firsts <- head(x, - window)
# Take the initial total and add the
# cumulative sum of lasts minus firsts
other_totals <- ___ + ___(___ - firsts)
# Build the output vector
c(
rep(NA, window - 1), # leading NA
initial_total / ___, # initial mean
other_totals / ___ # other means
)
}