首页 > 解决方案 > 在 R 中向量化迭代函数的最佳方法是什么?

问题描述

我正在使用一个引用给定个人投资组合价值的函数。要使用此函数,我需要遍历数据框的行并应用此函数:

x$cota <- 100

cotiza <- function(x){
  for(i in 1:nrow(x)) {
    if (i > 1){
      x[i,]$cota <- ((x[i,]$pl - x[i,]$mov)/x[i-1,]$pl) * x[i-1,]$cota
    }
  return (x)
}

这是该函数应用于的数据框:

    data    pl     mov cota
1 2018-01-01 500.0  250000  100
2 2018-01-02 525.0       0  100
3 2018-01-03 997.2 -100000  100
4 2018-01-04 500.0       0  100
5 2018-01-05 520.0       0  100

此数据帧上的函数输出应如下所示:

    data    pl     mov     cota
1 2018-01-01 500.0  250000   100.00
2 2018-01-02 525.0       0   105.00
3 2018-01-03 997.2 -100000 20199.44
4 2018-01-04 500.0       0 10128.08
5 2018-01-05 520.0       0 10533.20

有没有办法让这个函数矢量化,以便我可以将它应用到数据框?

标签: rvectorizationdata-science

解决方案


由于cota[3]依赖 的更新值cota[2]依赖cota[1],您不能对此函数进行简单的矢量化。有时您可以通过使用cumsumcumprod或类似的累积函数(它们仍然是迭代但在真正优化的代码中)来作弊,但它依赖于“简单的迭代累积”。然而,在这种情况下,一系列

cota[2] = cota[1] * (pl[2] - mov[2]) / pl[1],
cota[3] = cota[2] * (pl[3] - mov[3]) / pl[2]

如果你更换cota[2],你会得到

(cota[1] * (pl[2] - mov[2]) / pl[1]) * (pl[3] - mov[3]) / pl[2]

这实际上是

cota[1] * (pl[2]*pl[3] - pl[2]*mov[3] - pl[3]*mov[2] + mov[2]*mov[3]) / (pl[1] * pl[2])

它不会立即适用于简单的累积运算符。

一些提供各种滚动窗口的函数,特别是zoo::rollapply,但它们通常for在引擎盖下进行循环。(从技术上讲,我相信大多数*apply功能也在for引擎盖下进行循环,尽管很可能引擎盖下。)

如果您在使用此功能或类似功能时遇到性能问题,您始终可以使用Rcpp或类似的加速器。(一旦你进入Rcpp-territory,你可能会发现原始for循环会击败矢量化代码,甚至Rcpp-native 矢量化,尽管这在很大程度上取决于许多其他事情。)


推荐阅读