【问题标题】:Is it possible to vectorise the sequential update of the elements of a vector in R?是否可以对 R 中向量元素的顺序更新进行向量化?
【发布时间】:2011-01-14 19:47:06
【问题描述】:

是否可以像下面这样矢量化代码?

length(x) <- 100;
x[1]      <- 1;
y         <- rnorm(100);

for(i in 2:100) {
    x[i] <- 2 * y[i] * x[i-1];
}

我很欣赏这是一个微不足道的例子,但它可以说明这个想法。

我经常需要编写代码,其中向量中的第 i 个值取决于第 (i-1) 个值,如果可能,我想编写此代码而不需要 for 循环,作为分析表明具有这种类型操作的函数是我代码中的主要瓶颈。

此操作是否可向量化,因此我不需要在计算中使用for() 循环?

【问题讨论】:

  • 你找到了 R 最薄弱的环节:) 恐怕唯一的通用解决方案是将计算降到 C 级别。

标签: r vectorization


【解决方案1】:

一般来说,如果你想要一个矢量化的解决方案,你需要解决recurrence relation。

【讨论】:

  • 感谢您的链接,+1。我正在努力,以我有限的数学,将维基百科页面信息转化为解决 OP 问题的东西。如果不太涉及,您能否扩展您的答案以提出一种直接解决 OP 的 Q 的方法?
【解决方案2】:

在您的示例中,您可以计算出 x[i] 的公式,看看它是否可以向量化。在这种情况下,我认为 cumprod 可能会起作用。

x <- c(1, cumprod(2*y)[1:99])

在某些情况下,您还可以在卷积或递归模式下使用filter 命令。见?filter

但是,如果无法计算出适合上述模型之一的第 n 个值的公式,您可以尝试使用 inline 或 Rcpp 之类的包在循环中写入C/C++。

【讨论】:

  • 我没有得到与 @kaybenleroll 的 cumprod 解决方案相同的答案。我认为这也不在这里,for 循环不是累积超过 1、...、n,只是n-1 的函数。
  • 只是一个小索引错误:正确答案是c(1, cumprod(2*y[-1]))
【解决方案3】:

这个绘图命令的内部是等价的。重复运行它相当有趣:

绘图(c(1, 2^(2:length(x)-1)*cumprod(rnorm(99) )) )

【讨论】:

    【解决方案4】:

    您可以在 C++ 中编写非垂直化代码:

    library(inline)
    myfun <- cxxfunction(signature(y="numeric"), body='
    Rcpp::NumericVector yvec(y);
    int ysize = yvec.size();
    Rcpp::NumericVector result(ysize);
    if (ysize > 0) {
        result[0] = 1;
        for (int i = 1; i < ysize; i++) {
            result[i] = 2 * yvec[i] * result[i-1];
        }
    }
    return result;
    ', plugin="Rcpp")
    

    然后从 R 中调用这个函数:

    y <- rnorm(100);
    x <- myfun(y);
    

    【讨论】:

      【解决方案5】:

      我还没有这方面的完整细节,但看起来函数 filter() 将有助于满足我的需要。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-21
        • 1970-01-01
        • 2011-10-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多