web-dev-qa-db-ja.com

移動平均の計算

Rを使用して、マトリックス内の一連の値の移動平均を計算しようとしています。ただし、通常のRメーリングリスト検索はあまり役に立ちませんでした。 Rには 組み込み関数 が存在しないようで、移動平均を計算できます。パッケージはありますか?それとも自分で書く必要がありますか?

168
Jared
  • Zoo パッケージ(rollmean)のローリング平均/最大/中央値
  • TTR の移動平均
  • ma in 予測
126
f3lix

または、フィルターを使用して単純に計算することができます、ここに私が使用する関数があります:

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

dplyrを使用する場合は、上記の関数でstats::filterを指定するよう注意してください。

189
Matti Pastell

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からのコメントを取り入れて、これを行う1つの方法を次に示します。

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である場合、ゼロ除算エラーが発生するという問題が依然としてあります。

25
pipefish

data.table 1.12.0では、frollmeanNA、および+Inf-Infの値を慎重に処理する高速かつ正確なローリング平均を計算する新しいNaN関数が追加されました。

質問には再現可能な例がないため、ここで対処することはあまりありません。

?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
9
jangorecki

caToolsパッケージには、非常に高速な平均/最小/最大/ sdのローリングと他のいくつかの関数があります。私はrunmeanrunsdのみを使用しましたが、これまでに言及した他のパッケージの中で最も高速です。

8
eddi

RcppRollを使用して、C++で記述された非常に高速な移動平均を作成できます。 roll_mean関数を呼び出すだけです。ドキュメントは こちら にあります。

それ以外の場合、この(遅い)forループはトリックを行う必要があります。

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

実際、RcppRollは非常に優れています。

cantdutchthis によって投稿されたコードは、修正するウィンドウの4行目で修正する必要があります。

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

欠落を処理する別の方法は、 here です。

3番目の方法、 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,...)]
  }
}
7
Rodrigo Remedio

cantdutchthis および Rodrigo 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)
4

少し遅いですが、Zoo :: rollapplyを使用して行列の計算を実行することもできます。

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

ここで、xはデータセット、FUN = meanは関数です。また、min、max、sdなどに変更できます。幅はローリングウィンドウです。

0
Garima gulati