2009-04-13 9 views
136

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

104
  • volventi Mezzi/Massimi/mediane nel pacchetto zoo (rollmean)
  • MovingAverages in TTR
  • ma in forecast
169

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)}

+39

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

+28

Alcuni anni più tardi, ma dplyr ora ha una funzione di filtro, se hai questo pacchetto caricato usa 'stats :: filter' – blmoore

+0

' 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)? –

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.

1

tutte le opzioni elencate qui sono le medie mobili causali. se è richiesta una versione non causale, il pacchetto segnala ha alcune opzioni.

+0

Non molto utile solo nominare un pacchetto - almeno fornire i nomi delle funzioni ... –

7

È 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 
} 
+1

Puoi spiegarmi in dettaglio, come funziona questo algoritmo? Perché non riesco a capire l'idea –

21

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 
+6

Uno svantaggio di questa soluzione è che non può gestire le missioni: 'cumsum (c (1: 3, NA, 1: 3))' – Jthorpe

3

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,...)] 
    } 
} 
2

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)