Loading [MathJax]/jax/element/mml/optable/BasicLatin.js

72 votos

¿Cómo simular datos que satisfagan las limitaciones específicas como específica media y desviación estándar?

Esta pregunta está motivada por mi pregunta en el meta-análisis. Pero me imagino que también sería útil en contextos de enseñanza en la que desea crear un conjunto de datos que corresponde exactamente a una ya existente publicado conjunto de datos.

Sé cómo generar datos aleatorios de una distribución dada. Así, por ejemplo, si he leído acerca de los resultados de un estudio que había:

  • una media de 102,
  • una desviación estándar de 5.2 y
  • un tamaño de muestra de 72.

Yo podría generar datos similares usando rnorm en R. Por ejemplo,

set.seed(1234)
x <- rnorm(n=72, mean=102, sd=5.2)

Por supuesto, la media y la SD no sería exactamente igual a 102 y 5.2, respectivamente:

round(c(n=length(x), mean=mean(x), sd=sd(x)), 2)
##     n   mean     sd 
## 72.00 100.58   5.25 

En general estoy interesado en cómo simular datos que se ajusta a un conjunto de restricciones. En el caso anterior, las restricciones son del tamaño de la muestra, la media y la desviación estándar. En otros casos, puede haber restricciones adicionales. Por ejemplo,

  • un mínimo y un máximo en cualquiera de los datos o de la variable subyacente puede ser conocida.
  • la variable puede ser conocida a tomar sólo valores enteros o sólo la no-valores negativos.
  • los datos se pueden incluir múltiples variables con conocidos inter-correlaciones.

Preguntas

  • En general, ¿cómo puedo simular los datos que exactamente satisface un conjunto de restricciones?
  • Hay artículos escritos acerca de esto? Hay algún programa en R que hacer esto?
  • Por el bien de ejemplo, ¿cómo podría y debería simular una variable, por lo que tiene una determinada media y sd?

32voto

Niall Puntos 51

En general, para hacer de su media muestral y la varianza exactamente igual a un valor dado de antemano, usted puede apropiadamente cambio y la escala de la variable. Específicamente, si X1,X2,...,Xn es una muestra, a continuación, las nuevas variables

Zi=c1(Xi¯XsX)+c2

donde ¯X=1nni=1Xi es la media de la muestra y s2X=1n1ni=1(Xi¯X)2 es la varianza de la muestra son tales que la media de la muestra de la Zis'es exactamente c2 y su varianza de la muestra es exactamente c1. De una forma similar construido ejemplo, se puede restringir el rango de -

Bi=a+(ba)(Ximin

va a producir un conjunto de datos B_1, ..., B_n que está restringida al intervalo (a,b).

Nota: Estos tipos de cambio/escala, en general, el cambio de la distribución de la familia de los datos, incluso si los datos originales se trata de una ubicación a escala de la familia.

En el contexto de la distribución normal de la mvrnorm de la función en R permite simular normal (o multivariante normal) con los datos de un pre-especificado de la muestra media/covarianza estableciendo empirical=TRUE. En concreto, esta función simula los datos de la distribución condicional de una variable de distribución normal, dado que la media de la muestra y (co)varianza es igual a un valor dado de antemano. Tenga en cuenta que el resultado distribuciones marginales son no normales, como se ha señalado por @whuber en un comentario a la pregunta principal.

Aquí es un simple univariante ejemplo, cuando la media de la muestra (a partir de una muestra de n=4) está restringido a ser 0 y la desviación estándar de la muestra es de 1. Podemos ver que el primer elemento es mucho más similar a una distribución uniforme de una distribución normal:

library(MASS)
 z = rep(0,10000)
for(i in 1:10000)
{
    x = mvrnorm(n = 4, rep(0,1), 1, tol = 1e-6, empirical = TRUE)
    z[i] = x[1]
}
hist(z, col="blue")

\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ enter image description here

28voto

Sean Hanley Puntos 2428

Con respecto a su solicitud de documentos, hay:

Esto no es exactamente lo que usted está buscando, pero pueden servir de grano para el molino.


Hay otra estrategia que parece que nadie ha mencionado. Es posible generar N-k (pseudo) aleatorios de los datos de un conjunto de tamaño N que todo el conjunto cumple con k restricciones tan largo como el resto de los k de datos, se fijan en los valores adecuados. Los valores requeridos deben ser resueltos con un sistema de k ecuaciones, álgebra, y poco de grasa del codo.

Por ejemplo, para generar un conjunto de N de datos de una distribución normal que tiene una muestra dada decir, \bar x, y la varianza, s^2, usted necesitará para corregir los valores de dos puntos: y y z. Dado que la media de la muestra es:
\bar x = \frac{\sum_{i=1}^{N-2}x_i\; + \;y\!+\!z}{N} y debe ser: y = N\bar x\; - \;\left(\sum_{i=1}^{N-2}x_i\!+\!z\right) La varianza de la muestra es: s^2 = \frac{\sum_{i=1}^{N-2}(x_i - \bar x)^2\; + \;(y - \bar x)^2\!+\!(z - \bar x)^2}{N-1} por lo tanto (después de la sustitución de la anterior para y, frustrar / distribución, y reorganizar...), se obtiene: 2(N\bar{x}\! - \!\sum_{i=1}^{N-2}x_i)z - 2z^2 = N\bar{x}^2(N\!-\!1) + \sum_{i=1}^{N-2}x_i^2 + \left[\sum_{i=1}^{N-2}x_i\right)^2 - 2N\bar{x}\sum_{i=1}^{N-2}x_i - (N\!-\!1)s^2 Si tomamos a=-2, b=2(N\bar{x} - \sum_{i=1}^{N-2}x_i) y c como la negación de la RHS, podemos resolver para a z usando la fórmula cuadrática. Por ejemplo, en R, el siguiente código se puede utilizar:

find.yz = function(x, xbar, s2){
  N    = length(x) + 2
  sumx = sum(x)
  sx2  = as.numeric(x%*%x)          # this is the sum of x^2
  a    = -2
  b    = 2*(N*xbar - sumx)
  c    = -N*xbar^2*(N-1) - sx2 - sumx^2 + 2*N*xbar*sumx + (N-1)*s2
  rt   = sqrt(b^2 - 4*a*c)

  z    = (-b + rt)/(2*a)
  y    = N*xbar - (sumx + z)
  newx = c(x, y, z)
  return(newx)
}

set.seed(62)
x    = rnorm(2)
newx = find.yz(x, xbar=0, s2=1)
newx                                # [1] 0.8012701  0.2844567  0.3757358 -1.4614627
mean(newx)                          # [1] 0
var(newx)                           # [1] 1

Hay algunas cosas a entender sobre este enfoque. En primer lugar, no está garantizado para trabajar. Por ejemplo, es posible que su inicial N-2 datos son tales que no hay valores y y z existir que hacen de la varianza del conjunto resultante es igual a s^2. Considere la posibilidad de:

set.seed(22)    
x    = rnorm(2)
newx = find.yz(x, xbar=0, s2=1)
Warning message:
In sqrt(b^2 - 4 * a * c) : NaNs produced
newx                                # [1] -0.5121391  2.4851837        NaN        NaN
var(c(x, mean(x), mean(x)))         # [1] 1.497324

Segundo, mientras que la estandarización hace que las distribuciones marginales de todas sus variables más uniforme, este enfoque sólo afecta a los dos últimos valores, pero hace que sus distribuciones marginales sesgada:

set.seed(82)
xScaled = matrix(NA, ncol=4, nrow=10000)
for(i in 1:10000){
  x           = rnorm(4)
  xScaled[i,] = scale(x)
}

(insert plot)

set.seed(82)
xDf = matrix(NA, ncol=4, nrow=10000)
i   = 1
while(i<10001){
  x       = rnorm(2)
  xDf[i,] = try(find.yz(x, xbar=0, s2=2), silent=TRUE)  # keeps the code from crashing
  if(!is.nan(xDf[i,4])){ i = i+1 }                      # increments if worked
}

(insert plot)

Tercero, la muestra resultante no puede mirar muy normal; podría parecer que se ha 'outliers' (es decir, los puntos que vienen de distintos datos de proceso de generación de que el resto), ya que es esencialmente el caso. Esto es menos probable que sea un problema con muestras de mayor tamaño, como el ejemplo de las estadísticas de los datos generados deben converger los valores necesarios y por lo tanto necesitan menos ajuste. Con muestras más pequeñas, siempre se puede combinar este enfoque con el de aceptar / rechazar algoritmo que intenta de nuevo, si el generado de la muestra tiene forma de estadísticas (por ejemplo, la asimetría y la curtosis) que se encuentran fuera de los límites aceptables (cf., @cardenal del comentario), o extender este enfoque a generar una muestra con un fijo de la media, varianza, asimetría y curtosis (voy a dejar el álgebra hasta que, a pesar de que). Alternativamente, se podría generar un pequeño número de muestras y utilizar el uno con el más pequeño (decir) la prueba de Kolmogorov-Smirnov estadístico.

library(moments)
set.seed(7900)  
x = rnorm(18)
newx.ss7900 = find.yz(x, xbar=0, s2=1)
skewness(newx.ss7900)                       # [1] 1.832733
kurtosis(newx.ss7900) - 3                   # [1] 4.334414
ks.test(newx.ss7900, "pnorm")$statistic     # 0.1934226

set.seed(200)  
x = rnorm(18)
newx.ss200 = find.yz(x, xbar=0, s2=1)
skewness(newx.ss200)                        # [1] 0.137446
kurtosis(newx.ss200) - 3                    # [1] 0.1148834
ks.test(newx.ss200, "pnorm")$statistic      # 0.1326304 

set.seed(4700)  
x = rnorm(18)
newx.ss4700 = find.yz(x, xbar=0, s2=1)
skewness(newx.ss4700)                       # [1]  0.3258491
kurtosis(newx.ss4700) - 3                   # [1] -0.02997377
ks.test(newx.ss4700, "pnorm")$statistic     # 0.07707929S

(add plot)

11voto

tricasse Puntos 1610

Hay algún programa en R que hacer esto?

El Runuran R paquete contiene muchos métodos para la generación de variables aleatorias. Se utiliza C bibliotecas de la UNU.RAN (Universal No Uniforme generador de números Aleatorios) del proyecto. Mi propio conocimiento del campo de azar de la variable aleatoria generación es limitado, pero el Runuran viñeta proporciona una buena visión general. A continuación son los métodos disponibles en la Runuran paquete, tomado de la viñeta:

Continua distribuciones:

  • Adaptación Rechazo De Muestreo
  • Inversa De La Transformada De La Densidad De Rechazo
  • El polinomio de Interpolación de Inverse CDF
  • La Simple Relación de los Uniformes Método
  • Transforma La Densidad De Rechazo

Distribuciones discretas:

  • Discretos Rechazo Automático De La Inversión
  • Alias-Urna Método
  • Guía-Método de Tabla de Discretas de Inversión

Multivariante de las distribuciones de:

  • Hit-and-Run algoritmo con Relación-de-Uniformes Método
  • Multivariante Ingenuo Relación-de-Uniformes Método

Ejemplo:

Para un rápido ejemplo, supongamos que desea generar una distribución Normal acotada entre 0 y 100:

require("Runuran")

## Normal distribution bounded between 0 and 100
d1 <- urnorm(n = 1000, mean = 50, sd = 25, lb = 0, ub = 100)

summary(d1)
sd(d1)
hist(d1)

El urnorm() función es una conveniente función de contenedor. Yo creo que detrás de las escenas que se utiliza el Polinomio de Interpolación de Inverse CDF método, pero no estoy seguro. Para algo más complejo, digamos, un discreto distribución Normal acotada entre 0 y 100:

require("Runuran")

## Discrete normal distribution bounded between 0 and 100
# Create UNU.RAN discrete distribution object
discrete <- unuran.discr.new(pv = dnorm(0:100, mean = 50, sd = 25), lb = 0, ub = 100)

# Create UNU.RAN object using the Guide-Table Method for Discrete Inversion
unr <- unuran.new(distr = discrete, method = "dgt")

# Generate random variates from the UNU.RAN object
d2 <- ur(unr = unr, n = 1000)

summary(d2)
sd(d2)
head(d2)
hist(d2)

10voto

Chris Alparas Puntos 21

La técnica general es el Rechazo del Método", donde se acaba de rechazar los resultados que no cumplan las restricciones. A menos que tengas algún tipo de orientación (como MCMC), entonces usted podría ser la generación de una gran cantidad de casos (dependiendo del escenario) que son rechazadas!

Cuando usted está buscando algo como una media y desviación estándar y se puede crear una distancia métrica de algún tipo para decir lo lejos que están lejos de su meta, usted puede utilizar la optimización de la búsqueda de las variables de entrada que dará el resultado deseado valores.

Como un feo ejemplo, cuando vamos a buscar una aleatoria uniforme vector con longitud de 100 que tiene media=0 y desviación estándar=1.

# simplistic optimisation example
# I am looking for a mean of zero and a standard deviation of one
# but starting from a plain uniform(0,1) distribution :-)
# create a function to optimise
fun <- function(xvec, N=100) {
  xmin <- xvec[1]
  xmax <- xvec[2]
  x <- runif(N, xmin, xmax)
  xdist <- (mean(x) - 0)^2 + (sd(x) - 1)^2
  xdist
}
xr <- optim(c(0,1), fun)

# now lets test those results
X <- runif(100, xr$par[1], xr$par[2])
mean(X) # approx 0
sd(X)   # approx 1

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X