5 Stimmen

Wie kann man die folgende Sequenz erzeugen, ohne auf eine Schleife zurückzugreifen?

time<-c(10,20)
d<-NULL
for ( i in seq(length(time)))
d<-c(d,seq(0,(time[i]-1)))
d

Wenn time<-c(3000,4000,2000,...,5000) und die Zeitspanne 1000 beträgt, ist das Verfahren sehr langsam. Gibt es eine schnellere Möglichkeit, die Sequenz ohne Schleife zu erzeugen?

Vielen Dank für Ihre Hilfe.

8voto

Joris Meys Punkte 102836

Versuchen Sie d <- unlist(lapply(time,function(i)seq.int(0,i-1)))

Eine Nebenbemerkung: Eine Sache, die die ganze Sache verlangsamt, ist die Tatsache, dass der Vektor innerhalb der Schleife wächst.

> time<-sample(seq(1000,10000,by=1000),1000,replace=T)

> system.time({
+  d<-NULL
+  for ( i in seq(length(time)))
+  d<-c(d,seq(0,(time[i]-1)))
+  }
+ )
   user  system elapsed 
   9.80    0.00    9.82 

> system.time(d <- unlist(lapply(time,function(i)seq.int(0,i-1))))
   user  system elapsed 
   0.00    0.00    0.01 

> system.time(unlist(mapply(seq, 0, time-1)))
   user  system elapsed 
   0.11    0.00    0.11 

> system.time(sequence(time) - 1)
   user  system elapsed 
   0.15    0.00    0.16 

Edit : Zeitangaben auch für andere Lösungen hinzugefügt

6voto

G. Grothendieck Punkte 232059

Dies ist viel schneller als die Schleife, aber nicht ganz so schnell wie die mapply y lapply Lösungen, die zuvor gezeigt wurden; sie ist jedoch sehr einfach:

sequence(time) - 1

und verwendet intern eine lapply .

3voto

Andrie Punkte 169813
time<-c(10, 20, 30)
unlist(mapply(seq, 0, time-1))

 [1]  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14
[26] 15 16 17 18 19  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19
[51] 20 21 22 23 24 25 26 27 28 29

1voto

csgillespie Punkte 56872

Wie @Joris angedeutet hat, war der Grund für die schlechte Leistung Ihrer Lösung das Vektorwachstum. Wenn Sie nur die Größe des Vektors geschätzt und den Speicher entsprechend zugewiesen hätten, wäre Ihre Lösung in Ordnung gewesen - allerdings immer noch nicht optimal.

Nach dem Beispiel von @Joris benötigte Ihre Lösung auf meinem Rechner 22 Sekunden. Durch die Vorabzuweisung eines großen Vektors können wir dies auf etwa 0,25 Sekunden reduzieren

> system.time({
+   d = numeric(6000000); k = 1 
+   for (i in seq(length(time))){
+     l = time[i]-1
+     d[k:(k+l)] = 0:l
+     k = k +l + 1
+   }}
+ )
  user  system elapsed 
 0.252   0.000   0.255

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X