帮助加速R中的循环

帮助加速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 &

基本上,我想在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 <- 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