帮助加速R中的循环
基本上,我想在R中执行对角线平均。下面是一些改编自simsalabim包的代码,用于执行对角线平均。只是这很慢 有没有建议用矢量化来代替sapply帮助加速R中的循环,r,loops,R,Loops,基本上,我想在R中执行对角线平均。下面是一些改编自simsalabim包的代码,用于执行对角线平均。只是这很慢 有没有建议用矢量化来代替sapply reconSSA <- function(S,v,group=1){ ### S : matrix ### v : vector N <- length(v) L <- nrow(S) K <- N-L+1 XX <- matrix(0,nrow=L,ncol=K) IND &
reconSSA <- function(S,v,group=1){
### S : matrix
### v : vector
N <- length(v)
L <- nrow(S)
K <- N-L+1
XX <- matrix(0,nrow=L,ncol=K)
IND <- row(XX)+col(XX)-1
XX <- matrix(v[row(XX)+col(XX)-1],nrow=L,ncol=K)
XX <- S[,group] %*% t(t(XX) %*% S[,group])
##Diagonal Averaging
.intFun <- function(i,x,ind) mean(x[ind==i])
RC <- sapply(1:N,.intFun,x=XX,ind=IND)
return(RC)
}
reconSSA我无法让你的例子产生合理的结果。我认为你的函数有几个错误
XX
用于sapply
,但未在函数中定义
sapply
适用于1:N
,在您的示例中,N=144
,但x.b
只有115列
reconSSA
只返回x
不管怎样,我认为你想要:
data(AirPassengers)
x <- AirPassengers
rowMeans(embed(x,30))
借助于行和
,您可以将计算速度提高近10倍:
reconSSA_1 <- function(S,v,group=1){
### S : matrix
### v : vector
N <- length(v)
L <- nrow(S)
K <- N-L+1
XX <- matrix(0,nrow=L,ncol=K)
IND <- row(XX)+col(XX)-1
XX <- matrix(v[row(XX)+col(XX)-1],nrow=L,ncol=K)
XX <- S[,group] %*% t(t(XX) %*% S[,group])
##Diagonal Averaging
SUMS <- rowsum.default(c(XX), c(IND))
counts <- if(L <= K) c(1:L, rep(L, K-L-1), L:1)
else c(1:K, rep(K, L-K-1), K:1)
c(SUMS/counts)
}
all.equal(reconSSA(S, v, 1:10), reconSSA_1(S, v, 1:10))
[1] TRUE
library(rbenchmark)
benchmark(SSA = reconSSA(S, v, 1:10),
SSA_1 = reconSSA_1(S, v, 1:10),
columns = c( "test", "elapsed", "relative"),
order = "relative")
test elapsed relative
2 SSA_1 0.23 1.0000
1 SSA 2.08 9.0435
请重新确认示例数据。我添加了一些数据。谢谢你的提醒。太好了;通过一个可复制的例子,你会得到更好的答案。这不是我想要的。我们的想法是使用x.b(Hankel)的结构,并对反对角线进行平均,因为我们将寻求x.b的近似值,该近似值可能没有适当的结构(Hankel),因此使用对角线平均在一定程度上缓解了这个问题。这属于奇异谱分析的主题。我还修复了您提到的引用。如果您能解释一下您希望调用sapply
做什么,我将再次尝试。代码中不清楚您的意图。我希望它能做的是在第3页的底部。请参阅链接以获取PDF。非常好的矢量化,具有行和
!只需使用所需的行和部分(即sort(unique(…)
和.Call(“Rrowsum_matrix”,…)
:)行和是为了速度而编写的,我希望有更多这样的函数,专门用于数组上的分组操作。@Joshua我记得曾经用过这个函数,大约半年前。据我记忆所及,它确实使这东西又加速了4倍。但是输入中的一个小错误和您的R会话消失了:)。对于本例,可能不需要重新排序。因此,重新编写行和可能是非常值得的。结果表明,对于这个特殊的问题,不需要使用unique,并且整数组的使用大大加快了整个计算的速度。
reconSSA <- function(S,v,group=1){
N <- length(v)
L <- nrow(S)
K <- N-L+1
XX <- matrix(0,nrow=L,ncol=K)
IND <- row(XX)+col(XX)-1
XX <- matrix(v[row(XX)+col(XX)-1],nrow=L,ncol=K)
XX <- S[,group] %*% t(t(XX) %*% S[,group])
##Diagonal Averaging
.intFun <- function(i,x,ind) {
I <- ind==i
sum(x[I])/sum(I)
}
RC <- sapply(1:N,.intFun,x=XX,ind=IND)
return(RC)
}
reconSSA_1 <- function(S,v,group=1){
### S : matrix
### v : vector
N <- length(v)
L <- nrow(S)
K <- N-L+1
XX <- matrix(0,nrow=L,ncol=K)
IND <- row(XX)+col(XX)-1
XX <- matrix(v[row(XX)+col(XX)-1],nrow=L,ncol=K)
XX <- S[,group] %*% t(t(XX) %*% S[,group])
##Diagonal Averaging
SUMS <- rowsum.default(c(XX), c(IND))
counts <- if(L <= K) c(1:L, rep(L, K-L-1), L:1)
else c(1:K, rep(K, L-K-1), K:1)
c(SUMS/counts)
}
all.equal(reconSSA(S, v, 1:10), reconSSA_1(S, v, 1:10))
[1] TRUE
library(rbenchmark)
benchmark(SSA = reconSSA(S, v, 1:10),
SSA_1 = reconSSA_1(S, v, 1:10),
columns = c( "test", "elapsed", "relative"),
order = "relative")
test elapsed relative
2 SSA_1 0.23 1.0000
1 SSA 2.08 9.0435
reconSSA_2 <- function(S,v,group=1){
### S : matrix
### v : vector
N <- length(v)
L <- nrow(S)
K <- N-L+1
XX <- matrix(0,nrow=L,ncol=K)
IND <- c(row(XX)+col(XX)-1L)
XX <- matrix(v[row(XX)+col(XX)-1],nrow=L,ncol=K)
XX <- c(S[,group] %*% t(t(XX) %*% S[,group]))
##Diagonal Averaging
SUMS <- .Call("Rrowsum_matrix", XX, 1L, IND, 1:N,
TRUE, PACKAGE = "base")
counts <- if(L <= K) c(1:L, rep(L, K-L-1), L:1)
else c(1:K, rep(K, L-K-1), K:1)
c(SUMS/counts)
}
test elapsed relative
3 SSA_2 0.156 1.000000
2 SSA_1 0.559 3.583333
1 SSA 5.389 34.544872