R 中的居中移动平均线(不使用包)

Centered moving average in R (without using packages)

我一直在 R 中构建中心移动平均线的函数(没有使用任何包),并且遇到了如下挑战:

如您所知,居中移动平均线包括合并 'incomplete portions' 的概念(即在数据点的开始和结束处)。例如,考虑下面的向量 p:

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

在这种情况下,我感兴趣的中心移动平均线如下所示:

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

为了实现上述目标,我尝试使用 if 函数,如下所示:

wd表示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)
}

然后我输入下面一行来执行:

mov_avg(p, 3)

我遇到如下错误:

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

有人可以帮我实现这个功能吗?

谢谢!

基数 R 中这样的东西怎么样:

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

x <- c(NA, p, NA)
sapply(seq_along(x[-(1:(window - 1))]), function(i)
    mean(x[seq(i, i + window - 1)], na.rm = T))
#[1] 15 20 30 40 50 60 70 80 85

诀窍是添加侧翼 NAs,然后使用 meanna.rm = T


我知道你说的是 "without using packages",但使用 zoo::rollapply

更短
library(zoo)
rollapply(c(NA, p, NA), 3, mean, na.rm = T)
#[1] 15 20 30 40 50 60 70 80 85

另一种方法是创建一个函数,我们可以在其中使用变量 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

在一个列为x的矩阵中按行取均值,头尾分别附加前两个和后两个元素的均值。

apply( matrix( c(x, 
               c( x[1]+x[2])/2, head(x,-1) ),
               c( tail(x,-1), sum( tail(x,2))/2)  ),
               ncol = 3),
       1, mean)

我们也可以使用rowMeans

rowMeans(embed(c(NA, p, NA),  3)[, 3:1], na.rm = TRUE)
#[1] 15 20 30 40 50 60 70 80 85