嵌套for循环的矢量化

时间:2019-09-17 20:18:53

标签: r vectorization

我具有以下功能:

g.Bn = function(n) {
  Bn = 0
  for(k in 0:n) {
    res.of.loop = 0
    for(j in 0:k) {
      res.of.loop = res.of.loop + (-1)^j * (j + 1)^n * choose(k, j)
    }
    Bn = res.of.loop * 1/(k+1) + Bn
  }
  return(Bn)
}

这里是将其向量化的一种方法,而不是使用for循环吗?

2 个答案:

答案 0 :(得分:4)

您可以矢量化内部循环(按照@DaveT),并使用sapply:

g.Bn2 = function(n) {
  sum(sapply(0:n, function(k) {
    sum((-1)^(0:k) * (0:k + 1)^n * choose(k, 0:k)) * 1/(k+1)
  }))
}

或者向量化外循环的另一种可能性:

g.Bn3 = function(n) {
  f <- function(k, n) sum((-1)^(0:k) * (0:k + 1)^n * choose(k, 0:k)) * 1/(k+1)
  sum(Vectorize(f, vectorize.args = "k")(0:n, n))
}
> microbenchmark(g.Bn(100), g.Bn2(100), g.Bn3(100))
       expr      min        lq      mean   median        uq      max neval
  g.Bn(100) 1493.086 1533.9280 1841.3455 1585.354 1675.3575 9023.316   100
 g.Bn2(100)  617.063  650.7850  905.6899  738.230  788.7305 9224.460   100
 g.Bn3(100)  685.094  772.3785 1015.9182  816.945  860.1775 8213.777   100

答案 1 :(得分:0)

您可以将for-loop转换为mapreduce

在下面的示例中,purrr::map迭代所有数据,而sum将数字矢量简化为定标器(长度为1的数字矢量)。

g.Bn = function(n) {
    sum(
        purrr::map_dbl(0:n,function(k){
            sum(
                purrr::map_dbl(0:k,function(j){
                    (-1)^j * (j + 1)^n * choose(k, j)
                })
            ) * 1/(k+1)

        })
    )
}


似乎内部循环中的所有j都可以替换为0:k

g.Bn = function(n) {
    sum(
        purrr::map_dbl(0:n,function(k){
            sum((-1)^(0:k) * (0:k + 1)^n * choose(k, 0:k)) * 1/(k+1)
        })
    )
}