2009-04-13 25 views
136

Estoy tratando de usar R para calcular la media móvil sobre una serie de valores en una matriz. La búsqueda normal de la lista de correo R no ha sido muy útil. No parece haber un built-in function en R que me permita calcular los promedios móviles. ¿Alguno paquete proporciona uno? ¿O necesito escribir el mío?Cálculo de la media móvil

Respuesta

104
  • medios de rodadura/Máximos/medianas en el paquete zoo (rollmean)
  • MovingAverages en TTR
  • ma en forecast
169

o simplemente puede calcularla usando el filtro, aquí está la función I utilizar:

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

+39

Debo señalar que "lados = 2" puede ser una opción importante en casos de uso de muchas personas que no quieren pasar por alto. Si solo desea información final en su promedio móvil, debe usar lados = 1. – evanrsparks

+28

Algunos años después, pero dplyr ahora tiene una función de filtro, si tiene este paquete cargado use 'stats :: filter' – blmoore

+0

' sides = 2' es equivalente a align = "center" para el zoo :: rollmean o RcppRoll :: roll_mean . 'sides = 1' es equivalente a la alineación" derecha ".No veo una manera de hacer alineación "izquierda" o calcular con datos "parciales" (2 o más valores)? –

2

El paquete caTools tiene una media/min/max/sd de rodadura muy rápida y algunas otras funciones. Solo he trabajado con runmean y runsd y son los más rápidos de los otros paquetes mencionados hasta la fecha.

1

todas las opciones enumeradas aquí son promedios móviles causales. si se requiere una versión no causal, entonces el paquete señal tiene algunas opciones.

+0

No es muy útil simplemente nombrar un paquete; al menos dar los nombres de las funciones ... –

7

Puede usar RcppRoll para promedios de movimiento muy rápidos escritos en C++. Simplemente llame a la función roll_mean. Los documentos se pueden encontrar en here.

De lo contrario, este (más lento) bucle debería hacer el truco.

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

¿Puede explicarme en detalle cómo funciona este algoritmo? Porque no puedo entender la idea –

21

El uso de cumsum debe ser suficiente y eficiente. Asumiendo que tiene un vector x y desea una suma continua de n números

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

Una desventaja de esta solución es que no puede manejar las pérdidas: 'cumsum (c (1: 3, NA, 1: 3))' – Jthorpe

3

De hecho RcppRoll es muy bueno.

El código publicado por cantdutchthis debe ser corregido en la cuarta línea de la ventana se fijará:

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

Otra forma, que se ocupa de missings, se da here.

Una tercera forma, la mejora de cantdutchthis código para calcular promedios parciales o no, de la siguiente manera:

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

Con el fin de complementar la respuesta de cantdutchthis y 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) 
Cuestiones relacionadas