Per quanto riguarda la tua richiesta di documenti, c'è:
Questo non è proprio quello che stai cercando, ma potrebbe servire da grinta per il mulino.
C'è un'altra strategia che nessuno sembra aver menzionato. È possibile generare (pseudo) dati casuali da un set di dimensioni tale che l'intero set soddisfi i vincoli purché i restanti dati siano fissati su valori appropriati. I valori richiesti dovrebbero essere risolvibili con un sistema di equazioni, algebra e grasso al gomito. N k k kN−kNkkk
Ad esempio, per generare un insieme di dati da una distribuzione normale che avrà una determinata media del campione, , e varianza, , sarà necessario fissare i valori di due punti: e . Poiché la media di esempio è: deve essere:
La varianza del campione è:
quindi (dopo aver sostituito sopra , sventando / distribuendo e riorganizzando ... ) noi abbiamo:
ˉ x s 2 y z ˉ x = ∑ N - 2 i = 1 x iNx¯s2yz
yy=N ˉ x
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
y a = - 2 b = 2 ( N ˉ x - ∑ N - 2 i = 1 x i ) c z2(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 prendiamo , e come negazione dell'RHS, possiamo risolvere per usando la
formula quadratica . Ad esempio, in , è possibile utilizzare il seguente codice:
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
Ci sono alcune cose da capire su questo approccio. Innanzitutto, non è garantito il funzionamento. Ad esempio, è possibile che le prime dati sono tali da non valori e esistono che faranno la varianza dei risultanti impostato uguale . Tener conto di: 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
In secondo luogo, mentre la standardizzazione rende le distribuzioni marginali di tutte le vostre variate più uniformi, questo approccio influenza solo gli ultimi due valori, ma rende le loro distribuzioni marginali distorte:
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
}
In terzo luogo, il campione risultante potrebbe non sembrare molto normale; potrebbe sembrare che abbia "valori anomali" (ovvero punti che provengono da un processo di generazione di dati diverso rispetto al resto), dal momento che essenzialmente è così. È meno probabile che ciò costituisca un problema con dimensioni del campione più grandi, poiché le statistiche del campione dai dati generati dovrebbero convergere ai valori richiesti e quindi necessitano di meno aggiustamenti. Con campioni più piccoli, è sempre possibile combinare questo approccio con un algoritmo di accettazione / rifiuto che riprova se il campione generato ha statistiche di forma (ad esempio, asimmetria e curtosi) che sono al di fuori dei limiti accettabili (cfr. Commento di @ cardinale ) o estendere questo approccio per generare un campione con una media fissa, varianza, asimmetria ekurtosi (lascerò l'algebra a te, però). In alternativa, è possibile generare un piccolo numero di campioni e utilizzare quello con la statistica Kolmogorov-Smirnov più piccola (diciamo).
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