Щодо Вашого запиту на документи, є:
Це не зовсім те, що ви шукаєте, але може служити приводом для млина.
Є ще одна стратегія, яку, схоже, ніхто не згадував. Можна згенерувати (псевдо) випадкові дані з набору розміру таким чином, що весь набір відповідає обмеженням до тих пір, поки решта даних фіксуються у відповідних значеннях. Необхідні значення повинні бути вирішені за допомогою системи рівнянь, алгебри та деякої ліктьової змазки. N−kNkkk
Наприклад, щоб генерувати набір даних із звичайного розподілу, який матиме задану середню вибірку та дисперсію, , вам потрібно буде зафіксувати значення двох точок: та . Оскільки середнє значення вибірки: має бути:
Дисперсія вибірки:
таким чином (після заміни вищевказаного на , складання / розповсюдження та перестановки ... ) ми отримуємо:
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
Якщо візьмемо , , і як заперечення РЗС ми можемо вирішити для використовуючи
квадратичну формулу . Наприклад, у , може бути використаний такий код:
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
Щодо цього підходу слід зрозуміти. По-перше, це не гарантовано працює. Наприклад, можливо, що ваші початкові дані такі, що не існує значень і які зроблять дисперсію отриманого набору рівним . Поміркуйте: 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
По-друге, хоча стандартизація робить граничні розподіли всіх ваших змінних більш рівномірними, такий підхід впливає лише на два останні значення, але робить їх граничні розподіли перекошеними:
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
}
По-третє, отриманий зразок може виглядати не дуже нормально; це може виглядати так, що у нього є "чужі люди" (тобто пункти, що надходять з іншого процесу генерування даних, ніж решта), оскільки це, по суті, так. Це менш ймовірно, що це проблема з більшими розмірами вибірки, оскільки статистика вибірки з генерованих даних повинна збігатися до необхідних значень і, таким чином, потребувати менших коригувань. При менших зразках, ви завжди можете поєднувати цей підхід з прийняттям / відхиленням алгоритму , який намагається знову , якщо згенерований зразок має статистичні форми (наприклад, асиметрія і ексцес) , які виходять за межі допустимих меж (див, @ кардинальські коментарів ), або продовжити цей підхід для створення вибірки з фіксованою середньою, дисперсією, косою такуртоз (хоча алгебру я залишаю тобі). Крім того, ви можете генерувати невелику кількість зразків і використовувати один з найменшими (скажімо) статистикою Колмогорова-Смірнова.
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