rmoving-average

Centered moving average in R (without using packages)


I have been constructing a function for centered moving average in R (without using any packages), and have encountered a challenge as below:

As you know, the centered moving average includes the concept of incorporating the 'incomplete portions' (i.e. at the beginning and the end of the datapoint). For example, consider below vector p:

p <- c(10,20,30,40,50,60,70,80,90)

In this case, centered moving average that I am interested in looks like this:

x <- ((10+20)/2, (10+20+30)/3, (20+30+40)/3 ..... (70+80+90)/3, (80+90)/2)

To achieve above, I tried function with if function as below:

wd means window size

mov_avg <- function(p, wd) {
  x <- c(0, cumsum(p))
  if ((p > p[1])&(p < p[length(p)])) {
    neut <- 1:(length(p)-(wd-1))
    upper <- neut+(wd-1)
    x <- (x[upper]-x[neut])/(upper-neut)
  } else if (p==p[1]) {
    neut <- 0
    upper <- neut+3
    x <- (x[upper]-x[neut])/(upper-1-neut)
  } else if (p==p[length(p)]) {
    upper <-(length(p)+1)
    neut <- (length(p)-(wd-2))
    x <- (x[upper]-x[neut])/(upper-neut)
  }
  return(x)
}

Then I entered below line to execute:

mov_avg(p, 3)

I encountered errors as below:

numeric(0)
Warning messages:
1: In if ((p > p[1]) & (p < p[length(p)])) { :
  the condition has length > 1 and only the first element will be used
2: In if (p == p[1]) { :
  the condition has length > 1 and only the first element will be used

Could someone help me out in making this a working function?

Thank you!


Solution

  • Another method is to create a function where we can adjust with variable windows

    mov_avg <- function(p, window) {
     mean_number = numeric()
     index = 1
     while(index < length(p)) {
       if (index == 1 | index == length(p) - 1) 
        mean_number = c(mean_number, mean(p[index:(index + window - 2)]))
       else 
        mean_number = c(mean_number, mean(p[index:(index + window - 1)]))
      index = index + 1
      }
      mean_number
    }
    
    mov_avg(p, 3)
    #[1] 15 30 40 50 60 70 80 85
    
    mov_avg(p, 2)
    #[1] 10 25 35 45 55 65 75 80