2012-10-19 41 views
7

Tôi có hai vector eg. Tôi muốn biết từng phần tử trong e phần trăm các phần tử trong g nhỏ hơn. Một cách để thực hiện điều này trong R là:Tăng tốc chức năng sử dụng mà trong một cuộc gọi dễ dàng trong 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) 

Với lớn e hoặc g, điều này mất rất nhiều thời gian để chạy. Làm cách nào để thay đổi hoặc điều chỉnh mã này để chạy nhanh hơn?

Lưu ý: Chức năng mf ở trên dựa trên mã từ chức năng mess trong gói tháo dỡ.

+0

Bạn có thể thay đổi mf cho 'mf <- function (p, v) {100 * bình (v <= p)} 'nhưng tôi không chắc nó sẽ giúp ích bao nhiêu. – Dason

+0

Cảm ơn Dason, nhưng dường như mất nhiều thời gian hơn – Paulo

+0

'vapply' thay vì 'sapply' có thể sẽ giúp ích. –

Trả lời

8

Lý do quá chậm vì bạn đang gọi hàm của mình length(e) lần. Nó không tạo ra sự khác biệt lớn cho các vectơ nhỏ, nhưng chi phí từ các cuộc gọi hàm R thực sự bắt đầu cộng với các vectơ lớn hơn.

Thông thường, bạn sẽ cần phải di chuyển này để biên dịch mã, nhưng may mắn là bạn có thể sử dụng 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

Cảm ơn @Joshua, câu trả lời tuyệt vời. Cải thiện tốc độ thật tuyệt vời. Một hiệu chỉnh nhỏ để có được cùng một đầu ra như trong hàm ban đầu: findInterval (e, sort (g))/length (g) – Paulo

Các vấn đề liên quan