Pour simuler des données avec une variance d'erreur variable, vous devez spécifier le processus de génération de données pour la variance d'erreur. Comme cela a été souligné dans les commentaires, vous l'avez fait lorsque vous avez généré vos données d'origine. Si vous avez des données réelles et que vous voulez essayer, il vous suffit d'identifier la fonction qui spécifie comment la variance résiduelle dépend de vos covariables. La façon standard de le faire est d'adapter votre modèle, de vérifier qu'il est raisonnable (autre que l'hétéroscédasticité) et d'économiser les résidus. Ces résidus deviennent la variable Y d'un nouveau modèle. Ci-dessous, je l'ai fait pour votre processus de génération de données. (Je ne vois pas où vous placez la graine aléatoire, donc ce ne seront pas littéralement les mêmes données, mais devraient être similaires, et vous pouvez reproduire la mienne exactement en utilisant ma graine.)
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)
Notez que R
le ? Plot.lm vous donnera un tracé (cf. ici ) de la racine carrée des valeurs absolues des résidus, superposée utilement avec un ajustement plus bas, ce qui est exactement ce dont vous avez besoin. (Si vous avez plusieurs covariables, vous voudrez peut-être les évaluer séparément pour chaque covariable.) Il y a le moindre indice d'une courbe, mais cela ressemble à une ligne droite qui fait un bon travail d'ajustement des données. Adaptons donc explicitement ce modèle:
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)
Nous n'avons pas à nous inquiéter du fait que la variance résiduelle semble également augmenter dans le graphique de localisation de l'échelle pour ce modèle - cela doit essentiellement se produire. Il y a à nouveau le moindre indice d'une courbe, nous pouvons donc essayer d'ajuster un terme au carré et voir si cela aide (mais cela ne fonctionne pas):
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
Si nous en sommes satisfaits, nous pouvons désormais utiliser ce processus comme module complémentaire pour simuler des données.
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
Notez que ce processus n'est pas plus garanti pour trouver le véritable processus de génération de données que toute autre méthode statistique. Vous avez utilisé une fonction non linéaire pour générer les SD d'erreur, et nous l'avons approximée avec une fonction linéaire. Si vous connaissez réellement le véritable processus de génération de données a priori (comme dans ce cas, parce que vous avez simulé les données d'origine), vous pourriez aussi bien l'utiliser. Vous pouvez décider si l'approximation ici est suffisante pour vos besoins. Cependant, nous ne connaissons généralement pas le véritable processus de génération de données et, sur la base du rasoir d'Occam, nous utilisons la fonction la plus simple qui correspond adéquatement aux données que nous avons fournies, la quantité d'informations disponibles. Vous pouvez également essayer des splines ou des approches plus sophistiquées si vous préférez. Les distributions bivariées me semblent raisonnablement similaires,