En cuanto a su solicitud de documentos, hay:
Esto no es exactamente lo que está buscando, pero podría servir como grano para el molino.
Hay otra estrategia que nadie parece haber mencionado. Es posible generar datos (pseudo) aleatorios a partir de un conjunto de tamaño modo que el conjunto completo cumpla con las restricciones siempre que los datos restantes se fijen en los valores apropiados. Los valores requeridos deben poder resolverse con un sistema de ecuaciones, álgebra y algo de grasa en el codo. N−kNkkk
Por ejemplo, para generar un conjunto de datos a partir de una distribución normal que tendrá una media de muestra dada, , y una varianza, , deberá fijar los valores de dos puntos: y . Como la media muestral es: debe ser:
La varianza muestral es:
tanto (después de sustituir lo anterior por , frustrar / distribuir y reorganizar ... ) obtenemos:
Nx¯s2yz
x¯=∑N−2i=1xi+y+zN
yy=Nx¯−(∑i=1N−2xi+z)
s2=∑N−2i=1(xi−x¯)2+(y−x¯)2+(z−x¯)2N−1
y2(Nx¯−∑i=1N−2xi)z−2z2=Nx¯2(N−1)+∑i=1N−2x2i+[∑i=1N−2xi]2−2Nx¯∑i=1N−2xi−(N−1)s2
Si tomamos , , como negación del RHS, podemos resolver usando la
fórmula cuadrática . Por ejemplo, en , se podría usar el siguiente código:
a=−2b=2(Nx¯−∑N−2i=1xi)czR
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 que debes entender sobre este enfoque. Primero, no se garantiza que funcione. Por ejemplo, es posible que sus datos iniciales de sean tales que no existan valores y que hagan que la varianza del conjunto resultante sea igual a . Considerar: N−2yzs2
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
En segundo lugar, mientras que la estandarización hace que las distribuciones marginales de todas sus variantes sean más uniformes, este enfoque solo afecta los dos últimos valores, pero hace que sus distribuciones marginales estén sesgadas:
set.seed(82)
xScaled = matrix(NA, ncol=4, nrow=10000)
for(i in 1:10000){
x = rnorm(4)
xScaled[i,] = scale(x)
}
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
}
Tercero, la muestra resultante puede no parecer muy normal; puede parecer que tiene "valores atípicos" (es decir, puntos que provienen de un proceso de generación de datos diferente al resto), ya que ese es esencialmente el caso. Es menos probable que esto sea un problema con tamaños de muestra más grandes, ya que las estadísticas de muestra de los datos generados deben converger a los valores requeridos y, por lo tanto, necesitan menos ajustes. Con muestras más pequeñas, siempre puede combinar este enfoque con un algoritmo de aceptación / rechazo que lo intenta nuevamente si la muestra generada tiene estadísticas de forma (por ejemplo, asimetría y curtosis) que están fuera de los límites aceptables (cf. comentario de @ cardinal ), o ampliar este enfoque para generar una muestra con una media fija, varianza, asimetría ycurtosis (aunque te dejaré el álgebra) Alternativamente, podría generar una pequeña cantidad de muestras y utilizar la que tenga la estadística más pequeña (digamos) de Kolmogorov-Smirnov.
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