条件滚动平均值

时间:2019-10-24 10:22:46

标签: r dplyr data.table

library(data.table)

set.seed(123)
d <- data.frame(ID = rep(1:5, each = 17), yearRef = rep(1998:2014, times = 5), y = sample(1:100, 17 * 5)) 

从1998年开始,我想为每个ID做y的7年滚动平均值。但是,条件是在每个滚动窗口中, 我只选择y的前5个最高值进行平均。例如。

第一个滚动窗口为

1998-2004年-仅对前5个最高“ y”值进行平均

1999-2005年-仅对前5个最高“ y”值进行平均 。

2007-2013年-仅对前5个最高的“ y”值进行平均

2008-2014年-仅对前5个最高的“ y”值进行平均

我对使用data.table实现这一目标很感兴趣。但是也有其他建议。这是我尝试过的

 d = setDT(d)
 d[, avg.Y := frollmean(y, 7), by = ID]

如何输入另一个参数,其中对于每个滚动的7年窗口,我仅选择前5个最高y值来计算均值?

编辑

我还可能会遇到这样的情况,即某些ID现在可能至少需要7年的数据才能进行移动平均,在这种情况下,上述函数会给我NA。对于这些ID,是否可以简单地采用算术平均值?例如如果某个ID拥有1998-2002年的数据,在这种情况下,我可以简单地获取1998-2002年y的平均值

3 个答案:

答案 0 :(得分:2)

首次使用frollapply(),但这似乎可行:

get_mean_top5 <- function(x) mean(-sort(-x, partial = 1:5)[1:5])
d[, test := frollapply(y, 7, FUN = get_mean_top5), by = ID]

函数get_mean_top5()过滤出前5个最高值,然后取平均值。其他更易读的形式是:

get_mean_top5 <- function(x) mean(mean(x[order(x, decreasing=TRUE)[1:5]]))

答案 1 :(得分:2)

我们可以使用rollapplyr中的zoo并应用自定义函数来计算每个滚动窗口中前5个值的mean

library(data.table)
library(zoo)

setDT(d)
d[, avg.Y:= rollapplyr(y, 7,function(x) mean(tail(sort(x), 5)), fill = NA), by = ID]

对于观察数量少于窗口大小的情况,我们可以做到

d[, avg.Y:= if (.N > 6) 
            rollapplyr(y, 7,function(x) mean(tail(sort(x), 5)), fill = NA)  
            else mean(y), by = ID]

答案 2 :(得分:1)

更多步骤和一些重复的基本R解决方案:

df$seven_year_group <-  paste0(ave(as.integer(as.factor(df$yearRef)) %% 7,

                               as.integer(as.factor(df$yearRef)) %% 7,

                               FUN = seq.int), 

                           "_",

                           df$ID)

seven_year_averages <- data.frame(avg_y = do.call("rbind", lapply(split(df, df$seven_year_group),

                                             function(x){mean(tail(x[order(x$y), "y"], 5))})))



seven_year_averages$seven_year_group <- row.names(seven_year_averages)

df <- merge(df, seven_year_averages, by = "seven_year_group", all.x = TRUE)

数据:

set.seed(2019)

df <- data.frame(ID = rep(1:5, each = 17), yearRef = rep(1998:2014, times = 5), y = sample(1:100, 17 * 5))