簡體   English   中英

r 中嵌套 for 循環的替代方法,或者可能需要 Rcpp?

[英]an alternative to nested for loops in r OR possible Rcpp needed?

我有一個嵌套循環

X <- matrix(c(0.5,0,0,0.75), nrow = 2)
k = nrow(X)

ans1 <- 0
ans2 <- 0
for (aa in 1:k) {
  for (bb in 1:k) {
    for (cc in 1:k) {
      for (dd in 1:k) {
        ans1 = ans1 + (0.45 * X[aa,bb] * X[cc,dd])
        for (xx in 1:k) {
          for (yy in 1:k){ 
            ans2 = ans2 + (1.7*X[aa,bb]*X[xx,yy]*X[cc,dd] + 0.2*X[aa,xx]*X[bb,yy]*X[cc,dd])  
          }
        }
      }
    }
  }
}

但是必須是方陣的矩陣X可以是非常高的維度。 因此,這將大大減慢循環。 例如X = matrix(rnorm(10000),nrow = 100,byrow = T)

我想知道是否有更短的方法來壓縮它。 這將是可讀的,最重要的是稍微快一點。 我已經嘗試過expand.grid但這並沒有多大幫助。

例如對於ans1

library(tidyverse)
an1 <- expand.grid(rep(list(seq(length(X))),2)) %>% arrange_all()
an11 <- t(apply(an1, 1, function(x) as.vector(t(X))[x]))

但正如我所提到的,這並沒有提高速度。 有什么建議么? 我也認為 Rcpp 可能會有所幫助,但我不確定而且我還沒有嘗試過(c++ 語法不太好)。

您根本不需要使用循環。 由於您的ans1ans2代碼只是術語的總和,並且這些術語根本不交互,因此表達式簡化為

ans1simple <- 0.45*sum(X)^2
ans2simple <- 1.9*sum(X)^3

您可以在隨機數據上進行測試。 如果您不相信,請更改X的種子或大小:

set.seed(123)

X <- matrix(rnorm(9), nrow = 3)
k = nrow(X)

ans1 <- 0
ans2 <- 0
for (aa in 1:k) {
  for (bb in 1:k) {
    for (cc in 1:k) {
      for (dd in 1:k) {
        ans1 = ans1 + (0.45 * X[aa,bb] * X[cc,dd])
        for (xx in 1:k) {
          for (yy in 1:k){ 
            ans2 = ans2 + (1.7*X[aa,bb]*X[xx,yy]*X[cc,dd] + 0.2*X[aa,xx]*X[bb,yy]*X[cc,dd])  
          }
        }
      }
    }
  }
}

ans1simple <- 0.45*sum(X)^2
ans2simple <- 1.9*sum(X)^3
ans1 - ans1simple
#> [1] 2.220446e-16
ans2 - ans2simple
#> [1] -7.993606e-15

reprex package (v1.0.0) 於 2021 年 4 月 19 日創建

差異只是舍入誤差。

與 C++ 中的for循環相比,R 中的for循環非常慢。

C++ for循環語法與 R 的某些風格沒有太大區別。

我高度懷疑你可以顯着壓縮你的代碼。 但只是按照你非常嵌套的語法:

RCPP function:

//[[Rcpp::export]]
Rcpp::NumericVector foo(Rcpp::NumericMatrix& X) {
    Rcpp::NumericVector ans(2);
    int k = X.rows();
    for (int aa = 0; aa < k; ++aa) {
        for (int bb = 0; bb < k; ++bb) {
            for (int cc = 0; cc < k; ++cc) {
                for (int dd = 0; dd < k; ++dd) {
                    ans[0] += 0.45 * X[aa, bb] * X[cc, dd]l;
                    for (int xx = 0; xx < k; ++xx) {
                        for (int yy = 0; yy < k; ++yy) {
                            ans[1] += (1.7 * X[aa, bb] * X[xx, yy] * X[cc, dd] + 0.2 * X[aa, xx] * X[bb, yy] * X[cc, dd]);
                        }
                    }
                }
            }
        }
    }
    return ans;
}

在 R 端:

X <- matrix(c(0.5,0,0,0.75), nrow = 2)
ans <- foo(X)
ans1 <- ans[1]
ans2 <- ans[2]

使用上面的代碼插入和插入並不是不優化代碼的借口。 再次,減少循環次數。 你不應該都需要它們。


在看到@user2554330 的回答后(我懷疑是這種情況,但懶得解決),Rcpp 實現不會比 R 實現快得多(我懷疑你擔心這樣的邊際收益)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM