Sto provando a utilizzare R per calcolare la media mobile su una serie di valori in una matrice. La normale ricerca nella mailing list di R non è stata tuttavia molto utile. Non sembra esserci un built-in function in R mi consentirà di calcolare le medie mobili. Qualche pacchetto ne fornisce uno? O devo scrivere il mio?Calcolo della media mobile
risposta
Oppure si può semplicemente calcolare utilizzando il filtro, ecco la funzione I utilizzare:
ma <- function(x,n=5){filter(x,rep(1/n,n), sides=2)}
Il pacchetto caTools
ha una rotazione media molto veloce/min/max/sd e poche altre funzioni. Ho lavorato solo con runmean
e runsd
e sono il più veloce tra tutti gli altri pacchetti menzionati fino ad oggi.
tutte le opzioni elencate qui sono le medie mobili causali. se è richiesta una versione non causale, il pacchetto segnala ha alcune opzioni.
Non molto utile solo nominare un pacchetto - almeno fornire i nomi delle funzioni ... –
È possibile utilizzare RcppRoll
per medie mobili molto veloci scritte in C++. Basta chiamare la funzione roll_mean
. I documenti possono essere trovati here.
Altrimenti, questo ciclo (più lento) dovrebbe fare il trucco.
ma <- function(arr, n=15){
res = arr
for(i in n:length(arr)){
res[i] = mean(arr[(i-n):i])
}
res
}
Puoi spiegarmi in dettaglio, come funziona questo algoritmo? Perché non riesco a capire l'idea –
Utilizzare cumsum
dovrebbe essere sufficiente ed efficiente. Supponendo di avere un vettore x e si desidera una somma parziale di n numeri
cx <- c(0,cumsum(x))
rsum <- (cx[(n+1):length(cx)] - cx[1:(length(cx) - n)])/n
Uno svantaggio di questa soluzione è che non può gestire le missioni: 'cumsum (c (1: 3, NA, 1: 3))' – Jthorpe
Infatti RcppRoll
è molto buona.
Il codice inviato da cantdutchthis deve essere corretta nella quarta riga alla finestra fissato:
ma <- function(arr, n=15){
res = arr
for(i in n:length(arr)){
res[i] = mean(arr[(i-n+1):i])
}
res
}
altro modo, che gestisce missings, è dato here.
Un terzo modo, migliorando cantdutchthis codice per calcolare le medie parziali o no, segue:
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,...)]
}
}
Per completare la risposta di cantdutchthis e 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)
Vorrei sottolineare che "sides = 2" può essere un'opzione importante in molti casi di utilizzo che non vogliono trascurare. Se vuoi solo informazioni finali nella tua media mobile, dovresti usare sides = 1. – evanrsparks
Alcuni anni più tardi, ma dplyr ora ha una funzione di filtro, se hai questo pacchetto caricato usa 'stats :: filter' – blmoore
' sides = 2' equivale a align = "center" per zoo :: rollmean o RcppRoll :: roll_mean . 'sides = 1' equivale a" right "alignment.Non vedo un modo per fare allineamento "a sinistra" o calcolare con dati "parziali" (2 o più valori)? –