我正在尝试扩展this question的答案:具体来说,如何使用随机拦截来构建线性混合效果模型的模拟'从头开始(没有simulate.merMod
或arm
)。我问,因为我有兴趣重新采样从拟合模型中获得的参数估计值来模拟 - 而不是预测 - 新值的响应,同时重新采样固定效应参数估计,随机效应估计和残差方差。我试图这样做,但会很感激我对错误或如何改进过程的反馈。
我从Ben Bolker的建议开始,并使用mvrnorm()
从固定效应参数的采样分布中绘制新系数。
library(lme4)
mod1 <- lmer(Sepal.Length ~ Sepal.Width + (1 | Species), data = iris)
v <- vcov(mod1)
b <- mod1@beta
fixed <- MASS::mvrnorm(1000, mu=b, Sigma=v)
使用melt
重新整形重采样系数,并重命名列。
library(reshape)
library(dplyr)
fixed.resampled = reshape::melt(fixed, id.vars= "refs") %>%
dplyr::rename(species=X2)
从question about plotting random effects的答案中,提取并保存ranef
对象,在qq
中保存截距的方差,并设置截距估计,标准差和随机效果级别在数据框中。
randoms <- ranef(mod1, condVar = TRUE)
qq <- attr(ranef(mod1, condVar = TRUE)[[1]], "postVar")
rand.interc <- randoms$Species
df <- data.frame(Intercepts=randoms$Species[,1],
sd.interc=2*sqrt(qq[,,1:length(qq)]),
lev.names=rownames(rand.interc))
与固定效应系数一样,从采样分布中提取随机效应估计值。每个随机效应估计都是从具有均值df$Intercepts
和标准差df$sd.interc
的正态分布中采样的。创建一个空数组来保存样本。
ranef.resampled <- array(dim=c(1000,3))
使用物种特异性方法和标准偏差从每个物种的正态分布中取样。
for(i in 1:length(randoms$Species[,1])){
ranef.resampled[,i] <- rnorm(1000,mean=df$Intercepts[i],sd=df$sd.interc[i])
}
重塑并重命名数据框。
ranef.resampled <- data.frame(ranef.resampled) %>%
dplyr::rename(setosa=X1,versicolor=X2,virginica=X3) %>%
gather() %>%
dplyr::rename(species=key)
出于绘图目的,创建包含系数和随机效应估计值的数据框。
fixed.e <- data.frame(species=names(fixef(mod1)),estimate=fixef(mod1)[1:2])
ranef.e <- data.frame(species=row.names(rand.interc),estimate=rand.interc[,1])
把所有东西放在一起。
dfLong <- fixed.resampled %>%
dplyr::bind_rows(ranef.resampled) %>%
dplyr::bind_rows(fixed.e) %>%
dplyr::bind_rows(ranef.e) %>%
dplyr::rename(X2=species)
绘制系数和随机效应估计值。
ggplot(dfLong, aes (value,group=X2)) +
geom_density() +
geom_vline(data=dfLong,
aes(xintercept=estimate),
color="red",linetype="dashed") +
facet_grid(X2~.) +
theme_classic()
要模拟值,首先要创建一个新数据框来保存要执行模拟的值。在这里,我生成了1000个样本,这些样本与Species="setosa"
的原始数据的分布相匹配。
set.seed(101)
newDf <- data.frame(Sepal.Width = rnorm(1000,mean(iris$Sepal.Width[1:50]), sd(iris$Sepal.Width[1:50])), Species="setosa")
然后我使用这个新数据来模拟使用simulate.merMod
的结果(这是在simulate()
模型对象上调用mer
时调用的结果。
simulated.setosa <- data.frame(setosa=simulate(mod1, nsim=1, newdata=newDf)[1:1000,])
我想要做的是在不使用simulate()
的情况下生成类似的预测。到目前为止,我采取了以下步骤。 Sum:截距,&#39; width&#39;的参数估计乘以&#39; width&#39;的模拟值,以及&#39; setosa的重采样随机效应估计值。&#39;
sim.setosa <- data.frame(setosa=fixed[1:1000,1] + fixed[1:1000,2] * newDf$Sepal.Width[1:1000] + ranef.resampled[1:1000,2])
然后我使用以下内容来比较这两个模拟的输出。虽然我不希望它们完全匹配(重采样系数在simulate()
内部,但我不认为它与我尝试拼凑模拟的输出相同。
ggplot() +
geom_density(data=simulated.setosa,aes(setosa)) +
geom_density(data=sim.setosa,aes(setosa),col="red") +
theme_classic() +
xlim(c(0,10))