Calcul de moyenne mobile
-
09-09-2019 - |
Question
Je suis en train d'utiliser R pour calculer la moyenne mobile sur une série de valeurs dans une matrice. La recherche normale de la liste de diffusion R n'a pas été très utile cependant. Il ne semble pas être un fonction intégrée R va me permettre de calculer moyennes mobiles. Est-ce que les paquets fournissent un? Ou dois-je écrire mon propre?
Autres conseils
Ou vous pouvez simplement calculer l'aide du 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.
L'utilisation cumsum
doit être suffisante et efficace. En supposant que vous avez un vecteur x et que vous voulez une somme en cours d'exécution de nombres n
cx <- c(0,cumsum(x))
rsum <- (cx[(n+1):length(cx)] - cx[1:(length(cx) - n)]) / n
Comme indiqué dans les commentaires par @mzuther, cela suppose qu'il n'y a pas nas dans les données. pour faire face à ceux qui nécessiterait la division de chaque fenêtre par le nombre de valeurs non-NA. Voici une façon de le faire, 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
Il a encore la question que si toutes les valeurs de la fenêtre sont NAs alors il y aura une division par zéro erreur.
data.table 1.12.0 nouvelle fonction frollmean
a été ajoutée pour le calcul de roulement rapide et exacte signifie en ménageant NA
, NaN
et +Inf
, les valeurs -Inf
.
Comme il n'y a pas d'exemple reproductible dans la question il n'y a pas beaucoup plus pour répondre ici.
Vous pouvez trouver plus d'informations sur ?frollmean
dans le manuel, également disponible en ligne à l'adresse ?frollmean
.
Exemples de 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
Le paquet caTools
a rouler très vite moyenne / min / max / sd et quelques autres fonctions. Je n'ai travaillé avec runmean
et runsd
et ils sont les plus rapides de l'un des autres paquets mentionnés à ce jour.
Vous pouvez utiliser RcppRoll
pour les moyennes mobiles très rapides écrits en C ++. Il suffit d'appeler la fonction roll_mean
. Docs peuvent être trouvés .
Dans le cas contraire, ce (plus lent) pour la boucle 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
}
En fait RcppRoll
est très bon.
Le code écrit cantdutchthis doit être corrigée dans la quatrième ligne de la fenêtre fixée:
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 Disparitions, est donnée .
Une troisième façon, l'amélioration de code cantdutchthis pour calculer les moyennes partielles ou non, suivantes:
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,...)]
}
}
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)
Bien qu'un peu lent, mais vous pouvez également 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 = moyenne est la fonction; vous pouvez également modifier à min, max, sd, etc et la largeur est la fenêtre de roulement.