2016-11-29 18 views
6

Tôi muốn tăng tốc độ tính toán của mình và nhận kết quả mà không cần sử dụng vòng lặp chức năng m. Ví dụ tái sản xuất:R: loại bỏ vòng lặp và mã tăng tốc

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 

Trong mỗi lần lặp của vòng lặp for chúng ta đang đối phó với ma trận không vector, vậy làm thế nào điều này có thể được vector hóa?

@ joel.wilson Mục đích của hàm này là tính tần số cặp của các phần tử. Vì vậy, sau đó chúng tôi có thể ước tính khả năng đưa vào cặp đôi.

Nhờ @Khashaa và @alexis_laz. Điểm chuẩn:

> 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

cốt lõi là gì mục đích của hàm? bạn có thể giải thích điều đó không! –

+0

Ma trận chỉ là vectơ có kích thước. – Tensibai

+0

Nếu tốc độ là mối quan tâm của bạn, thì bạn nên cân nhắc sử dụng các hàm áp dụng. – Ansjovis86

Trả lời

6

này cần được nhanh hơn đáng kể vì nó tránh được hoạt động trên indexing đôi

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 

Simple "đếm/thêm" hoạt động có thể hầu như luôn luôn được vector hóa

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

Tuyệt vời, sau đó nhanh hơn gấp 10 lần! Cảm ơn bạn. Nhưng tôi vẫn tự hỏi, chúng ta có thể làm điều này mà không có vòng lặp? – minem

+0

Có, chúng tôi có thể làm điều này mà không có vòng lặp. Xem bản cập nhật – Khashaa

+0

Cảm ơn bạn! Bạn có thể thêm chức năng đầu tiên của bạn (với vòng lặp) để trả lời tốt, vì vậy tôi có thể thêm một số điểm chuẩn cho tất cả 3 chức năng. – minem

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