如何在R中避免循环?

6
在我的R程序中,我有一个如下形式的“for”循环:
for(i in 1:I)  
{  
res[i] <- a[i:I] %*% b[i:I]   
}

其中resab是长度为I的向量。

有没有一种简单的方法可以避免这个循环并直接计算出res?如果有,那么这样做会更有效率吗?

提前感谢!


1
为什么要使用矩阵乘法来处理一维向量? - Marc in the box
3
可能是因为我是个自学无知的人... - Martin
2个回答

9
这是a*b的“反向累加和”。
rev(cumsum(rev(a) * rev(b)))

时间试验正在进行中... :-) - Carl Witthoft
@CarlWitthoft 可以继续,但是使用 cumsum() 函数时,乘法只会发生一次,因此它的时间复杂度为 _O(n)_。而循环应该以 O(n^2) 运行。 - ilir
2
即使在Justin的代码中将%*%替换为*,中位数时间也分别为360和87700微秒,所以cumsum明显更快。 - Carl Witthoft
感谢您的检查,@CarlWitthoft。我认为加速主要是因为乘法和加法只发生一次。 - ilir

2
只要res已经有长度I,那么for循环就不是“错误的”,而使用apply解决方案也不会更快。然而,使用apply可能更加简洁(尽管可能更难读懂)。像这样:
res <- sapply(seq_along(a), function(i) a[i:I] %*% b[i:I])

应该作为一行代码运行。


进一步解释我的第一句话。虽然在R中使用固有的向量化非常方便,而且通常是最快的方法,但并不总是必须避免使用for循环。在底层,apply系列函数确定输出的大小并在“循环”之前进行预分配。


只是为了明确-这并没有加速计算,与循环的计算速度相比,它并没有任何优势,对吧? - Marc in the box
如果for循环中的代码是res <- rbind(res, ...),那么使用apply函数的版本会更快。 - Justin
1
另外,使用 sum(a[i:1] * b[i:1]) 比矩阵乘法稍微快一些。 - ilir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接