2016-11-29 70 views
6

我想加快我的計算並獲得結果,而不使用函數m中的循環。重複的例子:R:擺脫循環和超速代碼

N <- 2500 
n <- 500 
r <- replicate(1000, sample(N, n)) 

m <- function(r, N) { 
    ic <- matrix(0, nrow = N, ncol = N) 
    for (i in 1:ncol(r)) { 
    p <- r[, i] 
    ic[p, p] <- ic[p, p] + 1 
    } 
    ic 
} 

system.time(ic <- m(r, N)) 
# user system elapsed 
# 6.25 0.51 6.76 
isSymmetric(ic) 
# [1] TRUE 

for循環中,我們正在處理的矩陣不是向量的每一次迭代,所以如何能夠量化?

@ joel.wilson該函數的目的是計算元素的成對頻率。所以之後我們可以估計成對包含概率。

感謝@Khashaa和@alexis_laz。基準:

> require(rbenchmark) 
> benchmark(m(r, N), 
+   m1(r, N), 
+   mvec(r, N), 
+   alexis(r, N), 
+   replications = 10, order = "elapsed") 
      test replications elapsed relative user.self sys.self user.child sys.child 
4 alexis(r, N)   10 4.73 1.000  4.63  0.11   NA  NA 
3 mvec(r, N)   10 5.36 1.133  5.18  0.18   NA  NA 
2  m1(r, N)   10 5.48 1.159  5.29  0.19   NA  NA 
1  m(r, N)   10 61.41 12.983  60.43  0.90   NA  NA 
+1

什麼是核心功能的目的?你能解釋一下嗎? –

+0

矩陣只是具有維度的向量。 – Tensibai

+0

如果速度是你關心的問題,那麼你應該考慮使用apply函數。 – Ansjovis86

回答

6

,因爲它避免了雙索引操作這應該更快是顯著

m1 <- function(r, N) { 
    ic <- matrix(0, nrow = N, ncol=ncol(r)) 
    for (i in 1:ncol(r)) { 
    p <- r[, i] 
    ic[, i][p] <- 1 
    } 
    tcrossprod(ic) 
} 

system.time(ic1 <- m1(r, N)) 
# user system elapsed 
# 0.53 0.01 0.55 

all.equal(ic, ic1) 
# [1] TRUE 

簡單「的計數/添加」操作幾乎總是可以矢量

mvec <- function(r, N) { 
    ic <- matrix(0, nrow = N, ncol=ncol(r)) 
    i <- rep(1:ncol(r), each=nrow(r)) 
    ic[cbind(as.vector(r), i)] <- 1 
    tcrossprod(ic) 
} 
+0

好極了,快10倍!謝謝。但我仍然懷疑,我們可以做到這一點沒有循環? – minem

+0

是的,我們可以做到這一點沒有循環。查看更新 – Khashaa

+0

謝謝!你可以添加你的第一個函數(用循環)來回答屁股,所以我可以爲所有3個函數添加一些基準。 – minem