我有一个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)
})
提前致谢。 罗恩
答案 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
包有一些有用的移动窗口函数,例如rollsum
和rollapply
。我不确定你的操作系统是什么,即你正在使用哪些并行软件包,但这里有一个简单的例子:
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)
##