245 votes

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 sur la liste de diffusion de R n'a pas été très utile. Il ne semble pas y avoir de fonction intégrée dans R me permettra de calculer des moyennes mobiles. Y a-t-il des paquets qui en fournissent ? Ou dois-je écrire le mien ?

252voto

Matti Pastell Points 4244

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.

56 votes

Je dois souligner que "sides=2" peut être une option importante dans les cas d'utilisation de nombreuses personnes qu'elles ne veulent pas négliger. Si vous ne voulez que des informations de suivi dans votre moyenne mobile, vous devez utiliser sides=1.

37 votes

Quelques années plus tard, dplyr a maintenant une fonction de filtre, si vous avez ce paquet chargé, utilisez stats::filter

0 votes

sides = 2 est équivalent à align="center" pour le zoo::rollmean ou RcppRoll::roll_mean. sides = 1 est équivalent à un alignement "à droite". Je ne vois pas comment faire un alignement "gauche" ou calculer avec des données "partielles" (2 valeurs ou plus) ?

170voto

f3lix Points 13634
  • Moyennes/maximales/médianes mobiles dans le cadre de la zoo paquet (rollmean)
  • Moyennes mobiles en TTR
  • ma en prévision

3 votes

Qu'est-ce que la moyenne mobile dans R ne contenant pas les valeurs futures d'un timestamp donné ? J'ai vérifié forecast::ma et il contient tout le voisinage, pas le droit.

2 votes

Essayez le stats::filter à la place. Vous pouvez y définir sides = 1 pour les valeurs passées uniquement. Par exemple stats::filter(x, rep(1,5), sides = 1)/5 pour la moyenne sur 5 valeurs.

38voto

pipefish Points 491

Utilisation de cumsum devrait être suffisant et efficace. En supposant que vous ayez un vecteur x et vous voulez une somme courante de n numéros

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

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

10 votes

L'inconvénient de cette solution est qu'elle ne permet pas de gérer les manques : cumsum(c(1:3,NA,1:3))

1 votes

Vous pouvez facilement lui faire gérer les NA en faisant cx <- c(0, cumsum(ifelse(is.na(x), 0, x))) .

0 votes

@Ricardo Cruz : il pourrait être préférable de supprimer les NA et d'ajuster la longueur du vecteur en conséquence. Pensez à un vecteur avec beaucoup de NA : les zéros tireront la moyenne vers zéro, tandis que la suppression des NA laissera la moyenne telle quelle. Tout dépend de vos données et de la question à laquelle vous voulez répondre, bien sûr :)

32voto

Jan Gorecki Points 316

Sur data.table 1.12.0 nouveau frollmean La fonction a été ajoutée pour calculer la moyenne glissante rapide et exacte avec précaution. NA , NaN et +Inf , -Inf valeurs.

Comme il n'y a pas d'exemple reproductible dans la question, il n'y a pas grand chose de plus à aborder ici.

Vous pouvez trouver plus d'informations sur ?frollmean dans le manuel, également disponible en ligne à l'adresse ?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

13voto

eddi Points 17947

Le site caTools Le paquet a une moyenne mobile/min/max/sd très rapide et quelques autres fonctions. Je n'ai travaillé qu'avec runmean et runsd et ils sont les plus rapides de tous les autres paquets mentionnés à ce jour.

1 votes

C'est génial ! C'est la seule fonction qui fait cela d'une manière agréable et simple. Et on est en 2018 maintenant...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X