2017-09-21 1 views
2

Nach this Antwort zu befassen, ich habe einen gleitenden Durchschnitt Funktion für eine Fenstergröße von 2, 3 und 4.R durchschnittliche Funktion bewegt sich mit Werten von weniger Fenstergröße

require(zoo) 
#MOVING AVERAGE FUNCTION 
get.mav <- function(df, n = 2){ 
    if(length(df) < n){ 
    return(df) 
    } 
    c(df[1:(n-1)],rollapply(df,width = n, mean, align="right")) 
} 

#DATA FRAME (dummy) 
ID <- c("d","b","a","a","c","e","b","d","b","b") 
Value <- c(4,5,5,3,2,1,6,9,5,5) 
df <-data.frame(ID,Value) 

# FUNCTION IMPLEMENTATION 
df <- with(df,df[order(ID),]) 
df$mav2 <- unlist(aggregate(Value~ID,df,get.mav,na.action = NULL,n=2)$Value) 
df$mav3 <- unlist(aggregate(Value~ID,df,get.mav,na.action = NULL,n=3)$Value) 
df$mav4 <- unlist(aggregate(Value~ID,df,get.mav,na.action = NULL,n=4)$Value) 

#OUTPUT 
ID Value mav2 mav3 mav4 
a 5 5 5 5 
a 3 4 3 3 
b 5 5 5 5 
b 6 5.5 6 6 
b 5 5.5 5.3 5 
b 5 5 5.3 5.25 
c 2 2 2 2 
d 4 4 4 4 
d 9 6.5 9 9 
e 1 1 1 1 

Die Funktion get.mav genau so funktioniert, verwendet es sollte. Ich möchte diese Funktion ändern, so dass

Für Fenstergröße 3, wenn df Länge 2 ist, dauert es den Mittelwert dieser beiden Elemente statt einfach df zurückzugeben.

Ähnlich für Fenstergröße 4, wenn die Länge 3 oder 2 ist, nimmt es mittlere dieser drei oder zwei Elemente eher einfach zurückgeben df.

Ich habe versucht, die if-Anweisungen, aber Vergleiche funktionieren nicht richtig. Jede Hilfe wäre willkommen.

Danke.

Antwort

1

Verwenden Sie für jede Breite ave, um rollapplyr von ID aufzurufen. partial = TRUE in rollapplyr verursacht es durchschnittliche Teilanzahl von Punkten in der Nähe des Anfangs.

library(zoo) 

roll <- function(x, group, w) { 
    ave(x, group, FUN = function(x) rollapplyr(x, w, mean, partial = TRUE)) 
} 

transform(df[order(df$ID), ], 
    mav2 = roll(Value, ID, 2), 
    mav3 = roll(Value, ID, 3), 
    mav4 = roll(Value, ID, 4) 
) 

oder alternativ:

w <- 2:4 
names(w) <- paste0("mav", w) 

with(df[order(df$ID), ], 
    data.frame(ID, Value, lapply(w, roll, x = Value, group = ID), check.names = FALSE) 
) 

Entweder gibt:

ID Value mav2  mav3  mav4 
1 a  5 5.0 5.000000 5.000000 
2 a  3 4.0 4.000000 4.000000 
3 b  5 5.0 5.000000 5.000000 
4 b  6 5.5 5.500000 5.500000 
5 b  5 5.5 5.333333 5.333333 
6 b  5 5.0 5.333333 5.250000 
7 c  2 2.0 2.000000 2.000000 
8 d  4 4.0 4.000000 4.000000 
9 d  9 6.5 6.500000 6.500000 
10 e  1 1.0 1.000000 1.000000 

Update: behoben.

+0

genial. Ich liebe, wie ordentlich dein Code ist. – urwaCFC