Effiziente Generierung von Zufallszahlen aus einer abgeschnittenen Normalverteilung

9

Ich möchte 50.000 Werte aus der Normalverteilung mit Mittelwert = 0 und SD-1 abtasten. Aber ich möchte die Werte auf [-3,3] begrenzen. Ich habe Code geschrieben, um dies zu tun, aber nicht sicher, ob es am effizientesten ist? Hoffte, einige Vorschläge zu bekommen.

%Vor%     
user1375871 25.12.2012, 21:43
quelle

3 Antworten

11

Wenn Sie wirklich auf Effizienz achten, wird dieses kurze Stück Rcpp-Code schwer zu schlagen sein. Speichern Sie Folgendes in einer Datei, sagen Sie /tmp/rnormClamp.cpp :

%Vor%

Verwenden Sie sourceCpp() (aus Rcpp ), um es zu erstellen und auszuführen. Das tatsächliche Zeichnen und Klemmen dauert auf meinem Computer etwa 4 Millisekunden:

%Vor%

Die Funktion clamp() sugar wurde in dieser vorherigen SO-Antwort von Romain vorgestellt, die auch feststellt, dass Sie die Version möchten 0.10.2 von Rcpp.

Edit: Per Bens Hinweis schien ich falsch verstanden zu haben. Hier ist eine Mischung aus C ++ und R:

%Vor%

was man an die frühere Datei anhängen kann. Dann:

%Vor%

Ich werde zu der logischen Indizierung und der Zeilenuntermenge zurückkehren, die ich nachschlagen muss. Vielleicht morgen. Aber 9 Millisekunden sind immer noch nicht schlecht :)

Bearbeiten 2: Sieht so aus, als hätten wir keine logische Indizierung. Das müssen wir hinzufügen. Diese Version macht es "von Hand", ist aber nicht viel schneller als die Indizierung von R:

%Vor%

Und die Ausgabe:

%Vor%     
Dirk Eddelbuettel 25.12.2012, 21:51
quelle
12

Etwas wie Ihr Code wird definitiv funktionieren, aber Sie überschätzen stark, wie viele Werte Sie benötigen. Da es eine bekannte Verteilung und eine ziemlich große Anzahl von Samples ist, wissen Sie, wie viele mehr oder weniger als 3 erscheinen werden.

%Vor%

Wenn Sie also bei einer Unentschieden von 50,000 nur etwa 135 außerhalb der Reichweite erhalten, ist es ziemlich einfach, ein paar mehr zu zeichnen, aber immer noch keine ungewöhnlich große Zahl, und es zu kürzen. Nehmen Sie einfach die ersten 50.000 von 50.500, die kleiner oder größer als 3 sind.

%Vor%

Ich habe die ersten zwei Zeilen 40.000 Mal ausgeführt und jedesmal eine Länge größer als 50000 zurückgegeben. Ein kleiner boolescher Check könnte garantieren, dass es immer funktioniert.

%Vor%

Bei mir läuft das fast 100% der Zeit in 6 ms. Es ist ein einfacher Weg, es in R zu tun, der sehr schnell ausgeführt wird, leicht zu lesen ist und keine Add-ons benötigt.

    
John 25.12.2012 22:57
quelle
8

John und Dirk haben schöne Beispiele für die Ablehnung Stichproben, die für die gegebene Frage in Ordnung sein sollte. Aber um einen anderen Ansatz zu geben, wenn Sie die kumulative Verteilungsfunktion und ihre Inverse (oder sinnvolle Näherungen davon) haben, können Sie einfach Daten aus einer gleichmäßigen Verteilung und Transformation erzeugen:

%Vor%

Für die gegebene Frage erwarte ich nicht, dass dies viel besser ist (wenn besser) als die Zurückweisungs-Sampling-Methoden, aber wenn Sie Daten zwischen 2 und 3 aus einer abgeschnittenen Normalen 0,1 generieren wollten, dann würde diese Methode wahrscheinlich viel effizienter. Es ist abhängig von der kumulativen und seine inverse (pnorm und qnorm in diesem Fall) und so wäre nicht so einfach wie die Ablehnung Stichprobe für eine Verteilung ohne diese einfach verfügbar.

    
Greg Snow 26.12.2012 16:55
quelle

Tags und Links