Kom igångKom igång gratis

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

Visa kurs

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
  )
}
Redigera och kör kod