避免R中有两个循环

我有一个可以卷积两个函数的R代码

convolveSlow <- function(x, y) {  
nx <- length(x); ny <- length(y)  
xy <- numeric(nx + ny - 1)  
for(i in seq(length = nx)) {  
 xi <- x[[i]]  
        for(j in seq(length = ny)) {  
            ij <- i+j-1  
            xy[[ij]] <- xy[[ij]] + xi * y[[j]]  
        }  
    }  
    xy  
}  

有没有办法删除两个for循环,并使代码运行更快?

谢谢

最佳答案
由于R在计算向量运算时速度非常快,所以在编程性能时要记住的最重要的一点是尽可能多地对您的操作进行矢量化.

这意味着要用矢量操作代替循环.这是我的快速卷积解决方案(每个长度为1000的输入向量为50倍):

convolveFast <- function(x, y) {
    nx <- length(x)
    ny <- length(y)
    xy <- nx + ny - 1
    xy <- rep(0, xy)
    for(i in (1:nx)){
        j <- 1:ny
        ij <- i + j - 1
        xy[i+(1:ny)-1] <- xy[ij] + x[i] * y
    }
    xy
}

你会注意到内循环(对于j中的)已经消失了.相反,我用一个向量操作替换它. j现在被定义为向量(j <1:ny).还要注意,我指的是整个向量y,而不是子集(即y而不是y [j]).

j <- 1:ny
ij <- i + j - 1
xy[i+(1:ny)-1] <- xy[ij] + x[i] * y

我写了一个小功能测量性能:

measure.time <- function(fun1, fun2, ...){
    ptm <- proc.time()
    x1 <- fun1(...)
    time1 <- proc.time() - ptm

    ptm <- proc.time()
    x2 <- fun2(...)
    time2 <- proc.time() - ptm

    ident <- all(x1==x2)

    cat("Function 1\n")
    cat(time1)
    cat("\n\nFunction 2\n")
    cat(time2)
    if(ident) cat("\n\nFunctions return identical results")

}

对于每个长度为1000的两个向量,我获得了98%的性能提升:

x <- runif(1000)
y <- runif(1000)
measure.time(convolveSlow, convolveFast, x, y)

Function 1
7.07 0 7.59 NA NA

Function 2
0.14 0 0.16 NA NA

Functions return identical results

转载注明原文:避免R中有两个循环 - 代码日志