2012-10-19 44 views
7

我有兩個向量eg。我想知道e中的每個元素g中元素的百分比是否更小。 R中實現這一點的一種方式是:加速功能,使用在一個藍寶石電話R

set.seed(21) 
e <- rnorm(1e4) 
g <- rnorm(1e4) 
mf <- function(p,v) {100*length(which(v<=p))/length(v)} 
mf.out <- sapply(X=e, FUN=mf, v=g) 

隨着大eg,這需要大量的時間來運行。我如何改變或修改這段代碼以使其運行速度更快?

注意:上面的mf函數基於dismo包中mess函數的代碼。

+0

你可以MF切換到'MF < - 功能(P,V){100 *平均值(V <= p)}'但我不確定這會有多大幫助。 – Dason

+0

謝謝Dason,但這似乎需要更多時間 – Paulo

+0

'vapply'而不是'sapply'可能會有所幫助。 –

回答

8

這是如此之慢的原因是因爲你打電話給你的功能length(e)次。它對於小向量沒有太大的區別,但是R函數調用的開銷真的開始與更大的向量相加。

通常情況下,你就需要把這個搬到編譯的代碼,但幸運的是,你可以使用findInterval

set.seed(21) 
e <- rnorm(1e4) 
g <- rnorm(1e4) 
O <- findInterval(e,sort(g))/length(g) 

# Now for some timings: 
f <- function(p,v) mean(v<=p) 
system.time(o <- sapply(e, f, g)) 
# user system elapsed 
# 0.95 0.03 0.98 
system.time(O <- findInterval(e,sort(g))/length(g)) 
# user system elapsed 
#  0  0  0 
identical(o,O) # may be FALSE 
all.equal(o,O) # should be TRUE 

# How fast is this on large vectors? 
set.seed(21) 
e <- rnorm(1e7) 
g <- rnorm(1e7) 
system.time(O <- findInterval(e,sort(g))/length(g)) 
# user system elapsed 
# 22.08 0.08 22.31 
+0

謝謝@Joshua,很好的回答。速度的提高是驚人的。一個小的修正,以獲得與原始函數相同的輸出:findInterval(e,sort(g))/ length(g) – Paulo