通过并行处理在R中的矩阵的每列上滑动窗口

时间:2014-06-24 13:55:15

标签: r matrix parallel-processing apply

我有一个2000列和3000行的大矩阵。对于每一列,我想做一个滑动窗口,其中我将15行合并在一起,然后向下走一行并对接下来的15行求和......然后用这些信息创建一个新矩阵。我有一个有效的功能(虽然看起来有点慢),但想并行运行,因为这是一个更大的脚本的一部分,如果我使用没有并行等效的应用函数,开放集群关闭。而且,我必须完成整个操作100次。稍后在脚本中,我使用parLapply或parSapply。

以下是非平行方式的代码:

# df is a matrix with 2000 columns and 3000 rows, all numeric and no NAs

size <- 15 # size of window
len <- nrow(df) - size + 1 # number of sliding windows to perform 

sumsmatrix <- apply(df, 2, function(x){
      result <- sapply(1:len, function(y){
      sum(x[y:(y+size-1)])
       })
      return(result)
      })

提前致谢。 罗恩

2 个答案:

答案 0 :(得分:3)

尝试使用cumsum,您不必再重复相同的数字。

sumsmatrix <- apply(df, 2, function(x)                   
                     cumsum(x)[size:nrow(df)] - c(0,cumsum(x)[1:(len-1)]))

它应该比你正在做的快100倍。


以下是它的工作原理:

我们只是说x只有5长,窗口大小为3,以便更轻松。

x <- 1:5
x
# [1] 1 2 3 4 5
cumsum(x)
# [1]  1  3  6 10 15

所以,cumsum(x)的第三个数字是你想要的第一个数,但是第四个和第五个数字太大了,因为它们包含前几个数字作为窗口的一部分。所以,你只需减去两个。

cumsum(x)[3:5]    
# [1] 6 10 15    
cumsum(x)[1:2]
# [1]    1  3

但是,对于第一个,你需要减去零。

cumsum(x)[3:5]    
# [1] 6 10 15    
c(0,cumsum(x)[1:2])
# [1] 0  1  3

答案 1 :(得分:0)

正如@Andrie所提到的,zoo包有一些有用的移动窗口函数,例如rollsumrollapply。我不确定你的操作系统是什么,即你正在使用哪些并行软件包,但这里有一个简单的例子:

library(doSNOW)
library(foreach)
library(zoo)
##
oldD <- matrix(
  sample(1:5, (2000*3000), replace=TRUE),
  ncol=2000)
##
cl <- makeCluster(3,"SOCK")
registerDoSNOW(cl)
##
newD <- foreach(j=1:ncol(oldD),
                .combine=cbind,
                .export="rollsum") %dopar% {

                  rollsum(oldD[,j],15)

                }
##
stopCluster(cl)
##