web-dev-qa-db-fra.com

Calcul de la moyenne mobile

J'essaie d'utiliser R pour calculer la moyenne mobile sur une série de valeurs dans une matrice. La recherche normale dans la liste de diffusion R n'a cependant pas été très utile. Il ne semble pas y avoir de fonction intégrée dans R me permettra de calculer les moyennes mobiles. Est-ce que des forfaits en fournissent un? Ou dois-je écrire le mien?

170
Jared
  • Moyenne/Maximum/Médiane glissants dans le package Zoo (rollmean)
  • MovingAverages in TTR
  • ma dans prévision
129
f3lix

Ou vous pouvez simplement le calculer en utilisant un filtre, voici la fonction que j'utilise:

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

Si vous utilisez dplyr, veillez à spécifier stats::filter dans la fonction ci-dessus.

192
Matti Pastell

Utiliser cumsum devrait être suffisant et efficace. En supposant que vous avez un vecteur x et que vous voulez une somme courante de n nombres

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

Comme souligné dans les commentaires de @mzuther, cela suppose qu'il n'y a pas d'AN dans les données. Pour traiter ces problèmes, il faudrait diviser chaque fenêtre par le nombre de valeurs non-NA. Voici une façon de le faire, en incorporant le commentaire de @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

Cela pose toujours le problème suivant: si toutes les valeurs de la fenêtre sont des NA, il y aura une erreur de division par zéro.

25
pipefish

Dans , la fonction data.table 1.12.0 a été ajoutée à la nouvelle fonction frollmean afin de calculer une moyenne rapide et précise de la moyenne roulante en manipulant soigneusement NA, NaN et _+Inf_, _-Inf_ valeurs.

Comme il n’ya pas d’exemple reproductible dans la question, il n’ya pas beaucoup plus à aborder ici.

Vous trouverez plus d’informations sur _?frollmean_ dans le manuel, également disponible en ligne à l’adresse suivante: ?frollmean .

Exemples du manuel ci-dessous:

_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
_
11
jangorecki

Le paquetage caTools a une moyenne rapide/min/max/sd et quelques autres fonctions. J'ai seulement travaillé avec runmean et runsd et ils sont les plus rapides de tous les autres packages mentionnés à ce jour.

8
eddi

Vous pouvez utiliser RcppRoll pour les moyennes mobiles très rapides écrites en C++. Appelez simplement la fonction roll_mean. Les documents peuvent être trouvés ici .

Sinon, cette boucle (plus lente) devrait faire l'affaire:

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

En fait, RcppRoll est très bon.

Le code affiché par cantdutchthis doit être corrigé dans la quatrième ligne de la fenêtre pour être corrigé:

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

Une autre façon, qui gère les ratés, est donnée ici .

Une troisième façon, améliorant le code cantdutchthis permettant de calculer des moyennes partielles ou non, est la suivante:

  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

Afin de compléter la réponse de cantdutchthis et 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

Bien qu'un peu lent, vous pouvez aussi utiliser Zoo :: rollapply pour effectuer des calculs sur des matrices.

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

où x est l'ensemble de données, FUN = mean est la fonction; vous pouvez également le changer en min, max, sd, etc. et la largeur correspond à la fenêtre défilante.

0
Garima gulati