Aan de slagGa gratis aan de slag

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

Cursus bekijken

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
  )
}
Code bewerken en uitvoeren