Щоб імітувати дані з різною дисперсією помилок, потрібно вказати процес генерації даних для дисперсії помилок. Як було зазначено в коментарях, ви робили це під час створення оригінальних даних. Якщо у вас є реальні дані та ви хочете спробувати це, вам просто потрібно визначити функцію, яка визначає, як залежить залишкова дисперсія від ваших коваріатів. Стандартний спосіб зробити це - підходити до вашої моделі, переконайтесь, що вона є розумною (крім гетеросцедастичності) та збережіть залишки. Ці залишки стають змінною Y нової моделі. Нижче я це зробив для вашого процесу генерації даних. (Я не бачу, де ви встановите випадкове насіння, тому вони буквально не будуть однаковими даними, але повинні бути схожими, і ви можете відтворити мою точно, використовуючи моє насіння.)
set.seed(568) # this makes the example exactly reproducible
n = rep(1:100,2)
a = 0
b = 1
sigma2 = n^1.3
eps = rnorm(n,mean=0,sd=sqrt(sigma2))
y = a+b*n + eps
mod = lm(y ~ n)
res = residuals(mod)
windows()
layout(matrix(1:2, nrow=2))
plot(n,y)
abline(coef(mod), col="red")
plot(mod, which=3)
Зауважте, що R
s . plot.lm дасть вам графік (пор., Тут ) квадратного кореня абсолютних значень залишків, корисно накладений з низьким вмістом, що саме те, що вам потрібно. (Якщо у вас є кілька коваріатів, можливо, ви хочете оцінити це проти кожного коваріату окремо.) Існує найменший натяк на криву, але це виглядає так, що пряма лінія добре справляється зі зведенням даних. Тож давайте прямо підходимо до цієї моделі:
res.mod = lm(sqrt(abs(res))~fitted(mod))
summary(res.mod)
# Call:
# lm(formula = sqrt(abs(res)) ~ fitted(mod))
#
# Residuals:
# Min 1Q Median 3Q Max
# -3.3912 -0.7640 0.0794 0.8764 3.2726
#
# Coefficients:
# Estimate Std. Error t value Pr(>|t|)
# (Intercept) 1.669571 0.181361 9.206 < 2e-16 ***
# fitted(mod) 0.023558 0.003157 7.461 2.64e-12 ***
# ---
# Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#
# Residual standard error: 1.285 on 198 degrees of freedom
# Multiple R-squared: 0.2195, Adjusted R-squared: 0.2155
# F-statistic: 55.67 on 1 and 198 DF, p-value: 2.641e-12
windows()
layout(matrix(1:4, nrow=2, ncol=2, byrow=TRUE))
plot(res.mod, which=1)
plot(res.mod, which=2)
plot(res.mod, which=3)
plot(res.mod, which=5)
Нас не потрібно турбувати, що залишкова дисперсія, схоже, збільшується і в масштабі розташування сюжету для цієї моделі - що, по суті, має відбутися. Знову є найменший натяк на криву, тому ми можемо спробувати помістити термін у квадрат і побачити, чи це допомагає (але це не так):
res.mod2 = lm(sqrt(abs(res))~poly(fitted(mod), 2))
summary(res.mod2)
# output omitted
anova(res.mod, res.mod2)
# Analysis of Variance Table
#
# Model 1: sqrt(abs(res)) ~ fitted(mod)
# Model 2: sqrt(abs(res)) ~ poly(fitted(mod), 2)
# Res.Df RSS Df Sum of Sq F Pr(>F)
# 1 198 326.87
# 2 197 326.85 1 0.011564 0.007 0.9336
Якщо ми цим задоволені, тепер ми можемо використовувати цей процес як доповнення для імітації даних.
set.seed(4396) # this makes the example exactly reproducible
x = n
expected.y = coef(mod)[1] + coef(mod)[2]*x
sim.errors = rnorm(length(x), mean=0,
sd=(coef(res.mod)[1] + coef(res.mod)[2]*expected.y)^2)
observed.y = expected.y + sim.errors
Зауважте, що цей процес не є більш гарантованим для пошуку справжнього процесу генерації даних, ніж будь-який інший статистичний метод. Ви використовували нелінійну функцію для генерування SD-кодів помилок, і ми наблизили її до лінійної функції. Якщо ви справді знаєте справжній процес генерації даних a priori (як у цьому випадку, тому що ви імітували оригінальні дані), ви можете також використовувати його. Ви можете вирішити, чи апроксимація тут достатня для ваших цілей. Ми, як правило, не знаємо справжнього процесу генерації даних, однак, і грунтуючись на бритві Occam, ми працюємо з найпростішою функцією, яка адекватно вписується в дані, які нам дали доступну кількість інформації. Ви також можете спробувати сплайни або більш фантазійні підходи, якщо вам зручніше. Біваріантні розподіли виглядають досить схоже на мене,