我如何向量化到四次嵌套的“ for”循环

时间:2019-07-23 20:05:20

标签: r loops nested

如何简化以下r代码。.因为要花很多时间

   I1 <- 0
   m <- 10
    for (k1 in 0:m) {
      for (k2 in 0:m) {
        for (s1 in 0:m) {
          for (s2 in 0:m) {
            I1 <- I1 + C.n(c((k1)/m,(k2)/m),uc) *
              C.n(c((s1)/m,(s2)/m),uc) *
              choose(m,k1) * choose(m,k2) *
              choose(m,s1) * choose(m,s2) *
              beta((k1) + (s1) + 1, 2*m-(k1)-(s1) + 1) *
              beta((k2) + (s2) + 1, 2*m-(k2)-(s2) + 1)
          }
        }
      }
    }

1 个答案:

答案 0 :(得分:1)

在我的第一条评论中,您可能会满意:

I1 <- 0
m <- 10
for (k1 in 0:m) {
  ch_mk1 <- choose(m,k1)
  for (k2 in 0:m) {
    ch_mk2 <- choose(m,k2)
    ch_mk <- ch_mk1 * ch_mk2
    for (s1 in 0:m) {
      ch_ms1 <- choose(m,s1)
      be_k1s1 <- beta((k1) + (s1) + 1, 2*m-(k1)-(s1) + 1)
      for (s2 in 0:m) {
        ch_ms2 <- choose(m,s2)
        be_k2s2 <- beta((k2) + (s2) + 1, 2*m-(k2)-(s2) + 1)
        I1 <- I1 + C.n(c((k1)/m,(k2)/m),uc) *
          C.n(c((s1)/m, (s2)/m), uc) *
          ch_mk * ch_ms1 * ch_ms2 *
          be_k1s1 * be_k2s2        
      }
    }
  }
}

(我应该注意,这里和所有代码都未经测试,因为我没有您的功能。)

尽管这仍然有点低效。实话实说,我认为您根本不需要for循环。 R的许多功能真的很喜欢一次在整个矢量上执行操作,其中choosebeta就在其中。

尝试一下,完全删除for循环:

eg <- expand.grid(k1 = 0:m, k2 = 0:m, s1 = 0:m, s2 = 0:m)
ch_mk1 <- choose(m, eg$k1)
ch_mk2 <- choose(m, eg$k2)
ch_ms1 <- choose(m, eg$s1)
ch_ms2 <- choose(m, eg$s2)
be_k1s1 <- beta((eg$k1) + (eg$s1) + 1, 2*m-(eg$k1)-(eg$s1) + 1)
be_k2s2 <- beta((eg$k2) + (eg$s2) + 1, 2*m-(eg$k2)-(eg$s2) + 1)

现在最大的问题是C.n(和类似的uc)。

  • 如果它可以将参数作为矢量处理,请尝试以下操作:

    I1 <- sum(
      C.n(c((eg$k1)/m, (eg$k2)/m), uc) *
        C.n(c((eg$s1)/m, (eg$s2)/m), uc) *
        ch_mk1 * ch_mk2 * ch_ms1 * ch_ms2 *
        be_k1s1 * be_k2s2
    )
    
  • 如果不能将其参数作为矢量处理(或者即使可以,但无论如何您都想使用它),则尝试以下操作:

    I1 <- sum(
      mapply(C.n, (eg$k1)/m, (eg$k2)/m, uc) *
        mapply(C.n, (eg$s1)/m, (eg$s2)/m, uc) *
        ch_mk1 * ch_mk2 * ch_ms1 * ch_ms2 *
        be_k1s1 * be_k2s2
    )
    

    因为这只是使用mapply,所以如果您决定采用多处理路线(例如,parallel包),它将很容易并行化,如@BenBolker在其评论中建议的那样。

    p>

意识到eg将成倍增长,因此使用0:10意味着11^4或14,641行。如果m实际上大了许多,则可能会遇到内存或向量长度限制。在这种情况下,您可以使用保留了外部两个循环(k1k2)并在内部两个循环(例如expand.grid上使用expand.grid(s1 = 0:m, s2 = 0:m)的混合解决方案)在那里进行矢量化。或相反(展开k1k2,循环s1s2)。