Rullande medelvärden
Rullande medelvärden (kallas ibland glidande medelvärden) används inom tidsserieanalys för att jämna ut brus. Värdet vid varje tidpunkt ersätts med medelvärdet av värdena vid närliggande tidpunkter (det så kallade fönstret).
Ett naturligt sätt att skriva den här funktionen är
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
}
Detta anropar mean() många gånger, vilket är ineffektivt. En lösning är att använda en variabel total så att du vid varje iteration av slingan tar bort det element du inte längre behöver och lägger till det nya.
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
}
Oavsett vilket är det mycket mer naturligt att skriva kod med slingor än vektoriserad kod, vilket kan försämra prestandan. Båda versionerna ovan är ineffektiva på sitt eget sätt. Innan du skriver C++-versionen i nästa övning ska vi skriva en version som använder vektorisering. rollmean1(), rollmean2() och en slumpmässig vektor, x, finns tillgängliga i din arbetsyta. Nu ska du slutföra funktionsdefinitionen för rollmean3() och jämföra prestandan för dessa funktioner.
Den här övningen är en del av kursen
Optimera R-kod med Rcpp
Interaktiv övning med praktiskt arbete
Testa den här övningen genom att slutföra den här exempelkoden.
# 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
)
}