Necesito generar números aleatorios siguiendo la distribución Normal dentro del intervalo . (Estoy trabajando en R.)
Sé que la función rnorm(n,mean,sd)
generará números aleatorios siguiendo la distribución normal, pero ¿cómo establecer los límites de intervalo dentro de eso? ¿Hay alguna función R particular disponible para eso?
x <- rnorm(n, mean, sd); x <- x[x > lower.limit & x < upper.limit]
Respuestas:
Parece que desea simular a partir de una distribución truncada y, en su ejemplo específico, una normal truncada .
Hay una variedad de métodos para hacerlo, algunos simples, otros relativamente eficientes.
Ilustraré algunos enfoques en su ejemplo normal.
Aquí hay un método muy simple para generar uno a la vez (en algún tipo de pseudocódigo):
Si la mayor parte de la distribución está dentro de los límites, esto es bastante razonable, pero puede ser bastante lento si casi siempre genera fuera de los límites.
En R, puede evitar el bucle uno a la vez calculando el área dentro de los límites y generar suficientes valores para que pueda estar casi seguro de que después de arrojar los valores fuera de los límites aún tiene tantos valores como sea necesario.
Puede utilizar aceptar-rechazar con alguna función de especialización adecuada durante el intervalo (en algunos casos, el uniforme será lo suficientemente bueno). Si los límites fueran razonablemente estrechos en relación con el SD pero no estuvieras muy lejos de la cola, una mayorización uniforme funcionaría bien con lo normal, por ejemplo.
Si tiene un cdf razonablemente eficiente y un cdf inverso (como
pnorm
yqnorm
para la distribución normal en R), puede usar el método cdf inverso descrito en el primer párrafo de la sección de simulación de la página de Wikipedia en la normal truncada . [En efecto, esto es lo mismo que tomar un uniforme truncado (truncado en los cuantiles requeridos, que en realidad no requiere ningún rechazo, ya que es solo otro uniforme) y aplicar el cdf normal inverso a eso. Tenga en cuenta que esto puede fallar si está muy lejos de la cola]Hay otros enfoques; la misma página de Wikipedia menciona la adaptación del método de zigurat , que debería funcionar para una variedad de distribuciones.
El mismo enlace de Wikipedia menciona dos paquetes específicos (ambos en CRAN) con funciones para generar normales truncadas:
Mirando a su alrededor, mucho de esto está cubierto en respuestas a otras preguntas (pero no exactamente duplicados ya que esta pregunta es más general que solo la normal truncada) ... vea una discusión adicional en
a. Esta respuesta
si. La respuesta de Xi'an aquí , que tiene un enlace a su artículo arXiv (junto con algunas otras respuestas valiosas).
fuente
El enfoque rápido y sucio es usar la regla 68-95-99.7 .
En una distribución normal, el 99.7% de los valores caen dentro de 3 desviaciones estándar de la media. Entonces, si establece su media en el medio de su valor mínimo y valor máximo deseados, y establece su desviación estándar en 1/3 de su media, obtendrá (en su mayoría) valores que se encuentran dentro del intervalo deseado. Entonces puedes limpiar el resto.
Recientemente me enfrenté a este mismo problema, tratando de generar calificaciones aleatorias de los estudiantes para los datos de las pruebas. En el código anterior, he usado
pmax
ypmin
para reemplazar los valores fuera de los límites con el valor mínimo o máximo de los límites. Esto funciona para mi propósito, porque estoy generando cantidades bastante pequeñas de datos, pero para cantidades más grandes le dará golpes notables en los valores mínimo y máximo. Por lo tanto, dependiendo de sus propósitos, puede ser mejor descartar esos valores, reemplazarlos conNA
s o "volver a tirarlos" hasta que estén dentro de los límites.fuente
sample(x=min:max, prob=dnorm(...))
tal vez sea una forma más fácil de hacerlo.sample(x=min:max, prob=dnorm(...))
que parece un poco más corto que tu respuesta.sample()
truco solo es útil si está tratando de elegir enteros aleatorios, o algún otro conjunto de valores discretos y predefinidos.No hay una función incorporada para los valores generados a partir de la distribución truncada, pero es trivial programar este método utilizando las funciones ordinarias para generar variables aleatorias. Aquí hay una
R
función simplertruncnorm
que implementa este método en unas pocas líneas de código.Esta es una función vectorizada que generará
N
variables aleatorias IID a partir de la distribución normal truncada. Sería fácil programar funciones para otras distribuciones truncadas a través del mismo método. Tampoco sería demasiado difícil programar las funciones asociadas de densidad y cuantil para la distribución truncada.fuente