Generando muestras aleatorias a partir de una distribución personalizada

16

Estoy tratando de generar muestras aleatorias de un pdf personalizado usando R. Mi pdf es:

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

Generé muestras uniformes y luego traté de transformarlo en mi distribución personalizada. Hice esto buscando el cdf de mi distribución ( FX(x) ) y configurándolo en la muestra uniforme ( ) y resolviendo para .ux

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

Para generar una muestra aleatoria con la distribución anterior, obtenga una muestra uniforme u[0,1] y resuelva para x in

32(xx33)=tu

Lo implementé Ry no obtengo la distribución esperada. ¿Alguien puede señalar la falla en mi entendimiento?

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
fuente
1
Debe ser un error de codificación. No uso R, así que no puedo decir cuál es exactamente el error, pero acabo de codificar su solución (teniendo cuidado de tomar la raíz media del polinomio cúbico, que siempre se encuentra entre 0 y 1), y Tengo un buen acuerdo entre las muestras y la distribución esperada. ¿Podría ser un problema con su buscador de raíz? ¿Qué hay de malo con las muestras que estás obteniendo?
jpillow
Probé su código (que no es muy eficiente, por cierto) y obtengo la distribución esperada.
Aniko
@jpillow y @Aniko Mi error. Cuando lo usé nsamples <- 1e6fue un buen partido.
Anand
2
@Anand Una forma es observar que , lo que permite el cálculo directo de en términos de . x=2sin(arcsin(u)/3)xu
whuber
1
@Anand en.wikipedia.org/wiki/…
whuber

Respuestas:

11

Parece que descubriste que tu código funciona, pero @Aniko señaló que podrías mejorar su eficiencia. Su mayor ganancia de velocidad probablemente vendría de la asignación previa de memoria para zque no la esté creciendo dentro de un ciclo. Algo así z <- rep(NA, nsamples)debería hacer el truco. Puede obtener una pequeña ganancia de velocidad al usar vapply()(que especifica el tipo de variable devuelto) en lugar de un bucle explícito (hay una gran pregunta SO en la familia de aplicaciones).

> 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

Y no necesitas el ;al final de cada línea (¿eres un converso de MATLAB?).

Richard Herron
fuente
Gracias por su respuesta detallada y por señalar vapply. ¡He estado codificando C/C++durante mucho tiempo y esa es la razón de la ;aflicción!
Anand
1
uniroot107