如何编写一个无限/圆形的滚动窗口?

时间:2015-07-31 15:55:03

标签: r loops

我尝试创建一个滚动窗口,当窗口的尾部经过向量的末尾时,回滚到向量的开头(假设向量长度始终至少和窗口大小一样)。我可以通过无限次重复我的向量,然后应用标准滚动窗口来有效地实现这一点。

我尝试做的事情可能有更好的名称,我不确定。

我在R工作,一种奇怪/黑客的方式是确保R填充矩阵的方式:

# Number of windows
n.reps <- 10

# Window Size
time <- 12

# Vector I want to applying the window to
# Assume that the length of this vector is always >= window size
t.lvls <- c(0, 0, 0, 0.25, 0.25, 0.25, 0.75, 0.75, 0.75, 1, 1, 1)

# If I know n.reps ahead of time, I can simply create n.reps
# vectors with the appropriate frameshift by using 
# matrix() and how it repeats values.
# This is effective but inelegant.
ref <- matrix(t.lvls, byrow=TRUE, nrow=n.reps, ncol=time+1)

use.lvls <- list() # holds the values in each window
for(i in 1:n.reps){
    use.lvls[[i]] <- ref[i,-(time+1)]
}

我使用了matrix(),因此我没有必要对滚动窗口部分进行实际编程,但我想我总是可以像rep(t.lvls, ceiling(n.reps/time))这样做并循环...但是对于大的n.reps,我可能不想走这条路线(对于矩阵方法也一样)。

1)我试图做什么名称?

2)有更优雅的方式来编程吗?

编辑:预期输出(通过上面的代码实现)

list(c(0, 0, 0, 0.25, 0.25, 0.25, 0.75, 0.75, 0.75, 1, 1, 1), 
c(0, 0, 0.25, 0.25, 0.25, 0.75, 0.75, 0.75, 1, 1, 1, 0), 
c(0, 0.25, 0.25, 0.25, 0.75, 0.75, 0.75, 1, 1, 1, 0, 0), 
c(0.25, 0.25, 0.25, 0.75, 0.75, 0.75, 1, 1, 1, 0, 0, 0), 
c(0.25, 0.25, 0.75, 0.75, 0.75, 1, 1, 1, 0, 0, 0, 0.25), 
c(0.25, 0.75, 0.75, 0.75, 1, 1, 1, 0, 0, 0, 0.25, 0.25), 
c(0.75, 0.75, 0.75, 1, 1, 1, 0, 0, 0, 0.25, 0.25, 0.25), 
c(0.75, 0.75, 1, 1, 1, 0, 0, 0, 0.25, 0.25, 0.25, 0.75), 
c(0.75, 1, 1, 1, 0, 0, 0, 0.25, 0.25, 0.25, 0.75, 0.75), 
c(1, 1, 1, 0, 0, 0, 0.25, 0.25, 0.25, 0.75, 0.75, 0.75))

2 个答案:

答案 0 :(得分:1)

如果您想要无穷无尽的供应,请考虑使用迭代器

rolliter<-function(values,window) {
  i<-0;
  values<-c(values,values);
  function() {i<<-i%%window+1;values[i:(i+window-1)]}}

匹配您的输出

nxt<-rolliter(t.lvls,12)
replicate(10,nxt(),simplify=FALSE)

但是,您可以继续致电nxt()以获取更多信息。

答案 1 :(得分:1)

建立@nongkrong的%%建议我写了以下函数:

f5 <- function(){
    len.tlvl <- length(t.lvls)
    vals <- (1:time + rep(0:(n.reps-1), each=time))%%len.tlvl
    use.inds <- matrix(vals, nrow=time)
    use.inds[use.inds==0] <- len.tlvl
    matrix(t.lvls[use.inds], nrow=time)
}

作为奖励,即使t.lvls(向量)的长度小于time(窗口大小),它也能正常工作。

当我正在抛光这个功能时,我看到了@A的答案。韦伯

rolliter<-function(values,window){
    i<-0;
    values<-c(values,values);
    function() {i<<-i%%window+1;values[i:(i+window-1)]}
}
f6 <- function(){
    nxt<-rolliter(t.lvls,12)
    replicate(10,nxt(),simplify=T)
}

我对其进行了修改,以便输出为matrix(我知道这不是原始&#39;预期输出的格式&#39;,但我看到它不应该& #39; t))。请注意,当f6的长度小于t.lvls时,time函数不起作用(同样,这不是我原始问题中的要求)。

比较这两种方法的计算时间:

> microbenchmark(f5(), f6())
Unit: microseconds
 expr    min     lq      mean  median      uq      max neval
 f5() 33.789 36.436  39.28334 37.8530 40.3800    62.77   100
 f6() 61.890 66.283 359.21862 69.9395 77.9295 28811.27   100

两者都很快并产生类似的结果,但f5()方法更快一些。