R移动平均函数处理小于window大小的值
R moving average function to deal with values less window size
根据 this 的回答,我对 window 大小为 2、3 和 4 使用了移动平均函数。
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
函数 get.mav
完全正常工作。我想改变这个功能
对于 window 尺寸 3,如果 df 长度为 2,它取这两个元素的平均值而不是简单地返回 df。
与 window 大小 4 类似,如果长度为 3 或 2,它取这三个或两个元素的平均值,而不是简单地返回 df。
我尝试了 if 语句,但比较无法正常工作。任何帮助将不胜感激。
谢谢。
对于每个宽度,使用 ave
调用 rollapplyr
by ID
。 partial = TRUE
in rollapplyr
导致它对开头附近的部分点数进行平均。
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)
)
或者:
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)
)
要么给出:
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
更新: 修复。
根据 this 的回答,我对 window 大小为 2、3 和 4 使用了移动平均函数。
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
函数 get.mav
完全正常工作。我想改变这个功能
对于 window 尺寸 3,如果 df 长度为 2,它取这两个元素的平均值而不是简单地返回 df。
与 window 大小 4 类似,如果长度为 3 或 2,它取这三个或两个元素的平均值,而不是简单地返回 df。
我尝试了 if 语句,但比较无法正常工作。任何帮助将不胜感激。
谢谢。
对于每个宽度,使用 ave
调用 rollapplyr
by ID
。 partial = TRUE
in rollapplyr
导致它对开头附近的部分点数进行平均。
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)
)
或者:
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)
)
要么给出:
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
更新: 修复。