Jeśli chodzi o twoją prośbę o dokumenty, istnieją:
Nie jest to dokładnie to, czego szukasz, ale może służyć jako młyn do młyna.
Jest inna strategia, o której nikt chyba nie wspomniał. Możliwe jest generowanie (pseudo) losowych danych ze zbioru o rozmiarze tak że cały zestaw spełnia ograniczenia, o ile pozostałe danych jest ustawione na odpowiednie wartości. Wymagane wartości powinny być możliwe do rozwiązania za pomocą układu równań , algebry i pewnego smaru łokciowego. N−kNkkk
Na przykład, aby wygenerować zestaw danych z rozkładu normalnego, który będzie miał podaną średnią próbkową, i wariancję, , musisz naprawić wartości dwóch punktów: i . Ponieważ średnia próbki to: musi być:
Przykładowa wariancja to:
ten sposób (po zamianie powyższego na , foliowanie / dystrybucja i zmiana kolejności ... ) otrzymujemy:
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
Jeśli weźmiemy , , oraz jako negacja RHS, możemy rozwiązać dla za pomocą
wzoru kwadratowego . Na przykład można użyć następującego kodu:
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
Podejście to należy zrozumieć. Po pierwsze, nie ma gwarancji, że zadziała. Na przykład, możliwe jest, że początkowe Dane są takie, że nie ma wartości i tego, że istnieją będzie wariancji Otrzymaną równy . Rozważać: 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
Po drugie, podczas gdy standaryzacja sprawia, że rozkłady krańcowe wszystkich twoich zmiennych są bardziej jednolite, to podejście wpływa tylko na dwie ostatnie wartości, ale sprawia, że ich rozkłady krańcowe są wypaczone:
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
}
Po trzecie, uzyskana próbka może nie wyglądać bardzo normalnie; może to wyglądać tak, jakby zawierało „wartości odstające” (tj. punkty, które pochodzą z innego procesu generowania danych niż reszta), ponieważ tak jest w istocie. Jest to mniej prawdopodobne, że będzie to stanowić problem w przypadku większych próbek, ponieważ statystyki próbek z wygenerowanych danych powinny być zbieżne z wymaganymi wartościami, a zatem wymagać mniejszego dostosowania. Przy mniejszych próbkach zawsze możesz połączyć to podejście z algorytmem akceptowania / odrzucania, który próbuje ponownie, jeśli wygenerowana próbka ma statystyki kształtu (np. Skośność i kurtoza), które są poza dopuszczalnymi granicami (por. Komentarz kardynała ) lub rozszerzyć takie podejście do generowania próbki o ustalonej średniej, wariancji, skośności ikurtoza (ale zostawię tobie algebrę). Alternatywnie, możesz wygenerować niewielką liczbę próbek i użyć tej z najmniejszą (powiedzmy) statystyką Kołmogorowa-Smirnowa.
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