Generieren von Zufallsstichproben aus einer benutzerdefinierten Verteilung

16

Ich versuche, Zufallsstichproben aus einem benutzerdefinierten PDF mit R zu generieren. Mein PDF lautet:

fX(x)=32(1-x2),0x1

Ich habe einheitliche Samples generiert und dann versucht, diese in meine benutzerdefinierte Distribution umzuwandeln. Dazu habe ich die cdf meiner Verteilung ( FX(x) ) gefunden und auf die einheitliche Stichprobe ( ) gesetzt und nach .ux

FX(x)=Pr[Xx]=0x32(1-y2)dy=32(x-x33)

Um eine Zufallsstichprobe mit der obigen Verteilung zu erzeugen, erhalten Sie eine einheitliche Stichprobe und lösen nach x in \ frac {3} {2} (x - \ frac {x ^ 3} {3}) = uu[0,1]x

32(x-x33)=u

Ich habe es in implementiert Rund bekomme nicht die erwartete Verteilung. Kann jemand auf den Fehler in meinem Verständnis hinweisen?

nsamples <- 1000;
x <- runif(nsamples);

f <- function(x, u) { 
  return(3/2*(x-x^3/3) - u);
}

z <- c();
for (i in 1:nsamples) {
  # find the root within (0,1) 
  r <- uniroot(f, c(0,1), tol = 0.0001, u = x[i])$root;
  z <- c(z, r);
}
Anand
quelle
1
Muss ein Codierungsfehler sein. Ich benutze kein R, kann also nicht genau sagen, was der Fehler ist - aber ich habe gerade Ihre Lösung verschlüsselt (wobei darauf geachtet wird, die mittlere Wurzel des kubischen Polynoms zu ziehen, das immer zwischen 0 und 1 liegt), und Ich bekomme eine gute Übereinstimmung zwischen den Proben und der erwarteten Verteilung. Könnte es ein Problem mit Ihrem Root-Finder sein? Was stimmt nicht mit den Proben, die Sie bekommen?
Jpillow
Ich habe Ihren Code ausprobiert (der übrigens nicht sehr effizient ist) und erhalte die erwartete Verteilung.
Aniko
@jpillow und @Aniko Mein Fehler. Als ich es benutzte nsamples <- 1e6, war es ein gutes Match.
Anand
2
@Anand Eine Möglichkeit besteht darin, zu beobachten, dass , was eine direkte Berechnung von in Bezug auf . x=2Sünde(Arcsin(u)/3)xu
whuber
1
@Anand en.wikipedia.org/wiki/…
whuber

Antworten:

11

Sie haben anscheinend herausgefunden, dass Ihr Code funktioniert, aber @Aniko hat darauf hingewiesen, dass Sie die Effizienz verbessern können. Ihr größter Geschwindigkeitsgewinn würde wahrscheinlich durch die Vorbelegung des Speichers entstehen, zdamit Sie ihn nicht in einer Schleife vergrößern. So etwas z <- rep(NA, nsamples)sollte den Trick machen. Möglicherweise erhalten Sie einen kleinen Geschwindigkeitsgewinn durch die Verwendung von vapply()(der den zurückgegebenen Variablentyp angibt) anstelle einer expliziten Schleife (es gibt eine große SO-Frage zur Apply-Familie).

> nsamples <- 1E5
> x <- runif(nsamples)
> f <- function(x, u) 1.5 * (x - (x^3) / 3) - u
> z <- c()
> 
> # original version
> system.time({
+ for (i in 1:nsamples) {
+   # find the root within (0,1) 
+   r <- uniroot(f, c(0,1), tol = 0.0001, u = x[i])$root
+   z <- c(z, r)
+ }
+ })
   user  system elapsed 
  49.88    0.00   50.54 
> 
> # original version with pre-allocation
> z.pre <- rep(NA, nsamples)
> system.time({
+ for (i in 1:nsamples) {
+   # find the root within (0,1) 
+   z.pre[i] <- uniroot(f, c(0,1), tol = 0.0001, u = x[i])$root
+   }
+ })
   user  system elapsed 
   7.55    0.01    7.78 
> 
> 
> 
> # my version with sapply
> my.uniroot <- function(x) uniroot(f, c(0, 1), tol = 0.0001, u = x)$root
> system.time({
+   r <- vapply(x, my.uniroot, numeric(1))
+ })
   user  system elapsed 
   6.61    0.02    6.74 
> 
> # same results
> head(z)
[1] 0.7803198 0.2860108 0.5153724 0.2479611 0.3451658 0.4682738
> head(z.pre)
[1] 0.7803198 0.2860108 0.5153724 0.2479611 0.3451658 0.4682738
> head(r)
[1] 0.7803198 0.2860108 0.5153724 0.2479611 0.3451658 0.4682738

Und Sie brauchen nicht das ;am Ende jeder Zeile (sind Sie ein MATLAB-Konverter?).

Richard Herron
quelle
Vielen Dank für Ihre ausführliche Antwort und für den Hinweis vapply. Ich habe schon C/C++sehr lange programmiert und das ist der Grund für ;Bedrängnis!
Anand
1
uniroot107