计算移动平均线

问题描述 投票:165回答:9

我正在尝试使用R来计算矩阵中一系列值的移动平均值。正常的R邮件列表搜索虽然不是很有帮助。 R中似乎没有一个built-in function可以让我计算移动平均线。有任何套餐提供吗?或者我需要自己写吗?

r moving-average r-faq
9个回答
123
投票
  • zoo包装中的滚动平均值/最大值/中位数(rollmean)
  • TTR中移动平均值
  • 但在forecast

188
投票

或者您可以使用过滤器简单地计算它,这是我使用的函数:

ma <- function(x, n = 5){filter(x, rep(1 / n, n), sides = 2)}

如果你使用dplyr,请注意在上面的函数中指定stats::filter


24
投票

使用cumsum应该足够有效。假设你有一个向量x,你想要一个n个数的运行总和

cx <- c(0,cumsum(x))
rsum <- (cx[(n+1):length(cx)] - cx[1:(length(cx) - n)]) / n

正如@mzuther的评论中所指出的,这假设数据中没有NA。处理那些需要将每个窗口除以非NA值的数量。这是一种方法,结合@Ricardo Cruz的评论:

cx <- c(0, cumsum(ifelse(is.na(x), 0, x)))
cn <- c(0, cumsum(ifelse(is.na(x), 0, 1)))
rx <- cx[(n+1):length(cx)] - cx[1:(length(cx) - n)]
rn <- cn[(n+1):length(cx)] - cn[1:(length(cx) - n)]
rsum <- rx / rn

这仍然存在这样的问题:如果窗口中的所有值都是NA,则会出现零除错误。


8
投票

caTools包具有非常快的滚动平均值/ min / max / sd以及其他一些功能。我只与runmeanrunsd合作,他们是迄今为止提到的任何其他套餐中最快的。


8
投票

你可以使用RcppRoll来快速移动平均值用C ++编写。只需调用roll_mean函数即可。可以找到文件here

否则,这个(较慢的)for循环应该可以解决问题:

ma <- function(arr, n=15){
  res = arr
  for(i in n:length(arr)){
    res[i] = mean(arr[(i-n):i])
  }
  res
}

8
投票

在data.table 1.12.0中添加了新的frollmean函数来计算快速和精确的滚动平均值,仔细处理NANaN+Inf-Inf值。

由于问题中没有可复制的例子,因此这里没有更多要解决的问题。

你可以在?frollmean找到更多关于?frollmean的信息。

以下手册中的示例:

library(data.table)
d = as.data.table(list(1:6/2, 3:8/4))

# rollmean of single vector and single window
frollmean(d[, V1], 3)

# multiple columns at once
frollmean(d, 3)

# multiple windows at once
frollmean(d[, .(V1)], c(3, 4))

# multiple columns and multiple windows at once
frollmean(d, c(3, 4))

## three above are embarrassingly parallel using openmp

7
投票

事实上RcppRoll非常好。

cantdutchthis发布的代码必须在第四行中更正到窗口固定:

ma <- function(arr, n=15){
  res = arr
  for(i in n:length(arr)){
    res[i] = mean(arr[(i-n+1):i])
  }
  res
}

处理失误的另一种方式是here

第三种方法,改进cantdutchthis代码以计算部分平均值,如下:

  ma <- function(x, n=2,parcial=TRUE){
  res = x #set the first values

  if (parcial==TRUE){
    for(i in 1:length(x)){
      t<-max(i-n+1,1)
      res[i] = mean(x[t:i])
    }
    res

  }else{
    for(i in 1:length(x)){
      t<-max(i-n+1,1)
      res[i] = mean(x[t:i])
    }
    res[-c(seq(1,n-1,1))] #remove the n-1 first,i.e., res[c(-3,-4,...)]
  }
}

4
投票

为了补充cantdutchthisRodrigo Remedio的答案;

moving_fun <- function(x, w, FUN, ...) {
  # x: a double vector
  # w: the length of the window, i.e., the section of the vector selected to apply FUN
  # FUN: a function that takes a vector and return a summarize value, e.g., mean, sum, etc.
  # Given a double type vector apply a FUN over a moving window from left to the right, 
  #    when a window boundary is not a legal section, i.e. lower_bound and i (upper bound) 
  #    are not contained in the length of the vector, return a NA_real_
  if (w < 1) {
    stop("The length of the window 'w' must be greater than 0")
  }
  output <- x
  for (i in 1:length(x)) {
     # plus 1 because the index is inclusive with the upper_bound 'i'
    lower_bound <- i - w + 1
    if (lower_bound < 1) {
      output[i] <- NA_real_
    } else {
      output[i] <- FUN(x[lower_bound:i, ...])
    }
  }
  output
}

# example
v <- seq(1:10)

# compute a MA(2)
moving_fun(v, 2, mean)

# compute moving sum of two periods
moving_fun(v, 2, sum)

0
投票

虽然有点慢但你也可以使用zoo :: rollapply来执行矩阵计算。

reqd_ma <- rollapply(x, FUN = mean, width = n)

其中x是数据集,FUN = mean是函数;你也可以把它改成min,max,sd等,宽度就是滚动窗口。

© www.soinside.com 2019 - 2024. All rights reserved.