Em relação à sua solicitação de trabalhos, há:
Isso não é exatamente o que você está procurando, mas pode servir como fonte para o moinho.
Há outra estratégia que ninguém parece ter mencionado. É possível gerar dados aleatórios (pseudo) a partir de um conjunto de tamanho modo que todo o conjunto atenda às restrições , desde que os dados restantes sejam fixados em valores apropriados. Os valores exigidos devem ser solucionáveis com um sistema de equações, álgebra e alguma graxa de cotovelo. N−kNkkk
Por exemplo, para gerar um conjunto de dados a partir de uma distribuição normal que terá uma dada média da amostra, , e a variância, , será necessário corrigir os valores de dois pontos: e . Como a média da amostra é: deve ser:
A variação da amostra é:
assim (após substituir o acima por , frustrar / distribuir e reorganizar ... ) Nós temos:
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
Se tomarmos , , e como a negação da RHS, podemos resolver em usando a
fórmula quadrática . Por exemplo, em , o seguinte código pode ser usado:
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
Há algumas coisas para entender sobre essa abordagem. Primeiro, não é garantido que funcione. Por exemplo, é possível que as suas iniciais dados são tais que não os valores e existentes que fará com que a variância dos resultantes definidas iguais . Considerar: y z s 2N−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
Segundo, enquanto a padronização torna as distribuições marginais de todas as suas variáveis mais uniformes, essa abordagem afeta apenas os dois últimos valores, mas distorce suas distribuições marginais:
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
}
Terceiro, a amostra resultante pode não parecer muito normal; pode parecer que tem 'outliers' (ou seja, pontos que provêm de um processo de geração de dados diferente do restante), já que esse é basicamente o caso. É menos provável que seja um problema com tamanhos de amostra maiores, pois as estatísticas da amostra dos dados gerados devem convergir para os valores necessários e, portanto, precisam de menos ajustes. Com amostras menores, você sempre pode combinar essa abordagem com um algoritmo de aceitação / rejeição que tenta novamente se a amostra gerada tiver estatísticas de forma (por exemplo, assimetria e curtose) que estão fora dos limites aceitáveis (cf., comentário do @ cardinal ) ou estender esta abordagem para gerar uma amostra com média fixa, variância, assimetria ecurtose (eu vou deixar a álgebra para você, no entanto). Como alternativa, você pode gerar um pequeno número de amostras e usar aquela com a menor (digamos) estatística 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