【问题标题】:How to avoid a loop here in R?如何避免R中的循环?
【发布时间】:2014-04-28 14:03:59
【问题描述】:

在我的 R 程序中,我有一个如下形式的“for”循环:

for(i in 1:I)  
{  
res[i] <- a[i:I] %*% b[i:I]   
}

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

有什么直接的方法可以避免这个循环并直接计算 res 吗?如果是这样,那会更有效吗?

提前致谢!

【问题讨论】:

  • 为什么要对一维向量使用矩阵乘法?
  • 可能是因为我是自学成才,一无所知...

标签: r loops for-loop


【解决方案1】:

这是a*b的“反向cumsum”

rev(cumsum(rev(a) * rev(b)))

【讨论】:

  • 计时赛正在进行中... :-)
  • @CarlWitthoft 继续,但是cumsum() 的乘法只发生一次,所以它在 O(n) 中运行。循环应该在 O(n^2) 中运行。
  • 即使在 Justin's 中将 %*% 替换为 *,中位时间也是 360 和 87700 微秒,因此毫无意外 cumsum 会快很多。
  • 感谢您检查@CarlWitthoft。我认为加速主要是由于乘法和加法只发生一次。
【解决方案2】:

只要res 的长度已经达到I,for 循环就不会“不正确”,并且应用解决方案不会真正更快。但是,使用 apply 可以更简洁......(如果可能不太可读)

类似这样的:

res <- sapply(seq_along(a), function(i) a[i:I] %*% b[i:I])

应该作为单线工作。


扩展我的第一句话。虽然使用 R 中可用的固有矢量化非常方便,而且通常是最快的方法,但避免 for 循环并不总是很重要。在下面,apply 系列决定了输出的大小并在“循环”之前预先分配它。

【讨论】:

  • 只是要明确一点 - 这不会加快循环的计算速度,是吗?
  • 正确。如果 for 循环中的代码是 res &lt;- rbind(res, ...),那么应用版本会快得多。
  • 另外,使用sum(a[i:1] * b[i:1]) 应该比矩阵乘法稍快。
猜你喜欢
  • 2021-08-10
  • 1970-01-01
  • 2011-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多