Что касается вашего запроса на документы, есть:
Это не совсем то, что вы ищете, но может служить зерном для мельницы.
Есть еще одна стратегия, о которой никто, кажется, не упомянул. Можно генерировать (псевдо) случайных данных из набора размера , чтобы весь набор удовлетворял ограничениям, при условии, что оставшиеся данных фиксированы в соответствующих значениях. Требуемые значения должны быть решаемы с помощью системы уравнений, алгебры и некоторого количества коленчатого смазочного материала. 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
Если мы берем , , и как отрицание RHS, мы можем решить для используя
квадратную формулу . Например, в , следующий код может быть использован:
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
Есть несколько вещей, чтобы понять об этом подходе. Во-первых, это не гарантирует работу. Например, возможно, что ваши исходные данные таковы, что не существует значений и , из-за которых дисперсия полученного набора будет равна . Рассмотреть возможность: 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
Во-вторых, в то время как стандартизация делает предельные распределения всех ваших вариантов более равномерными, этот подход влияет только на последние два значения, но делает их предельные распределения перекошенными:
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
}
В-третьих, полученный образец может выглядеть не совсем нормально; может показаться, что у него есть «выбросы» (т. е. точки, полученные из процесса генерации данных, отличного от остальных), поскольку это, по сути, так. Это менее вероятно, будет проблемой с большими размерами выборки, так как статистика выборки из сгенерированных данных должна сходиться к требуемым значениям и, следовательно, нуждается в меньшей корректировке. С небольшими выборками вы всегда можете объединить этот подход с алгоритмом принятия / отклонения, который повторяет попытку, если сгенерированный образец имеет статистику формы (например, асимметрию и эксцесс), которые находятся за пределами допустимых границ (см., Комментарий @ cardinal ), или расширяете этот подход для генерации выборки с фиксированным средним, дисперсией, асимметрией иkurtosis (я оставлю алгебру до вас, хотя). Кроме того, вы можете сгенерировать небольшое количество выборок и использовать одну с наименьшей (скажем) статистикой Колмогорова-Смирнова.
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