2016-11-29 68 views
6

Chciałbym przyśpieszyć moje obliczenia i uzyskać wyniki bez użycia pętli w funkcji m. Powtarzalny przykład:R: pozbywanie się pętli for i kod przyspieszenia

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 

W każdej iteracji pętli for mamy do czynienia z matrycy nie wektorze, tak jak to może być Vectorized?

@ joel.wilson Celem tej funkcji jest obliczenie parami częstotliwości elementów. Tak więc możemy oszacować prawdopodobieństwa włączenia parami.

Dzięki @Khashaa i @alexis_laz. Benchmarki:

> 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

co jest rdzeniem cel tej funkcji? mógłbyś to wyjaśnić! –

+0

Macierz jest po prostu wektorem z wymiarami. – Tensibai

+0

Jeśli zależy Ci na szybkości, powinieneś rozważyć użycie funkcji stosowania. – Ansjovis86

Odpowiedz

6

ten powinien być znacznie szybszy, ponieważ unika operacji na podwójne indeksowanie

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 „liczenie/dodanie” operacje mogą być prawie zawsze wektorowy

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

Świetnie, ponad 10 razy szybciej! Dziękuję Ci. Ale wciąż zastanawiam się, czy moglibyśmy to zrobić bez pętli? – minem

+0

Tak, możemy to zrobić bez pętli. Zobacz aktualizację – Khashaa

+0

Dziękujemy! Czy mógłbyś dodać swoją pierwszą funkcję (z pętlą), aby dobrze odpowiedzieć na dupę, więc mogę dodać benchmarki dla wszystkich 3 funkcji. – minem