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))
对于每个ID,我想从1998年开始对y
进行7年的滚动平均。但是条件是在每个滚动窗口中,我只选择y的前5个最高值来做平均值。例如
第一个滚动窗口是
1998-2004-只做前5个最高"y"值的平均值
1999-2005年-只计算前5个最高"y"值的平均值。.
2007-2013-只做前5个最高"y"值的平均值
2008-2014-只做前5个最高"y"值的平均值
我对使用数据感兴趣。能够实现这一点。不过也对其他建议持开放态度。以下是我尝试的
d = setDT(d)
d[, avg.Y := frollmean(y, 7), by = ID]
如何输入另一个参数,即对于每个滚动的7年窗口,我只选择前5个最高的y值来计算平均值?
编辑
我也可能遇到这样的情况,即一些ID可能没有至少7年的数据来进行移动平均,在这种情况下,上述函数将为我提供NA。对于这些ID,是否可以简单地取算术平均值?例如,如果ID有1998-2002年的数据,在这种情况下,我可以简单地取1998-2002年的y
的平均值吗
我们可以使用zoo
中的rollapplyr
,并应用自定义函数来计算每个滚动窗口中前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]
第一次使用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]]))
更多的步骤和一点重复的基本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))