2016-04-21 13 views
-1

Ich fragte mich, ob es einen einfacheren existiert (und möglicherweise effizienten) Weg, um die folgende Schleife schreibenVereinfachung und Verbesserung für Schleife

l = leg(u[1],k) 
for (i in 2:length(u)){l=rbind(l,leg(u[i],k))} 

wo leg ist eine benutzerdefinierte Funktion, die einen Vektor der Größe k zurückzugibt. Grundsätzlich möchte ich eine length(u) x k Matrix zurückgeben.

Mein Problem ist, dass die Berechnung sehr langsam ist, wenn length(u) groß ist, also könnte die Verwendung einiger intelligentere Funktionen (wie apply oder seine Varianten) es schneller machen würde.

+0

Vielleicht kann dies effizienter sein: 'l <- do.call (rbind, lapply (1: Länge (u), Funktion (i) Bein (u [i], k)))', sollten Sie dennoch überlegen um deine 'Bein'-Funktion mehr vektorisiert zu machen (wenn möglich), dh, du kannst'U' statt'U [i] annehmen' – digEmAll

+0

Die Vorbelegung der Matrix kann auch verbessern: 'l <-Matrix (nrow = Länge (u), k) ' ' für (i in 1: Länge (u)) {l = l [i,] (l, Bein (u [i], k))} – DeveauP

Antwort

1

Entgegen der landläufigen Meinung, ist sapply nicht unbedingt schneller als ein for Schleife

testen wir ein paar verschiedene Methoden mit microbenchmark

library(microbenchmark) 
u<-1:10 
k<-3 

Ich erfinde hier eine Funktion zum Zwecke der Prüfung:

leg<-function(u,k){u**(1:k)} 

Lassen Sie uns verschiedene Methoden testen:

method1<-function(u,k){ 
    l = leg(u[1],k) 
    for (i in 2:length(u)){l=rbind(l,leg(u[i],k))} 
} 
method2<-function(u,k){ 
    l<-matrix(nrow = length(u),ncol = k) 
    for (i in 1:length(u)){l[i,]<-leg(u[i],k)} 
} 
method3<-function(u,k){ 
    l <- do.call(rbind,lapply(1:length(u),function(i)leg(u[i],k))) 
} 

Jetzt:

microbenchmark(times = 100, method1(u,k),method2(u,k),method3(u,k)) 
      expr min  lq  mean median  uq max neval 
method1(u, k) 30.031 32.6920 36.88837 34.2125 41.4350 53.219 100 
method2(u, k) 21.668 25.8490 29.60131 27.1800 32.6915 70.705 100 
method3(u, k) 21.667 26.2295 29.42637 27.3700 33.0715 51.699 100 

Wenn wir vektorisieren unsere Funktion:

leg2<-function(u,k){ 
    result<-matrix(nrow = length(u),ncol = k); 
    for(i in 1:k){result[,i]<-u**i} 
} 
microbenchmark(times = 100, method1(u,k),method2(u,k),method3(u,k),leg2(u,k)) 

Unit: microseconds 
     expr min  lq  mean median  uq max neval 
method1(u, k) 28.891 31.1710 34.79391 32.692 37.8235 64.243 100 
method2(u, k) 20.527 24.7085 29.20205 26.229 31.3610 79.068 100 
method3(u, k) 22.428 24.7090 28.49507 26.610 31.1710 71.465 100 
leg2(u, k) 6.462 7.6030 9.03213 8.363 8.7430 19.768 100 

So etwa 3-mal schneller!

Verwandte Themen