qqmath函数使用lmer软件包的输出产生很好的随机效应图。也就是说,qqmath非常适合绘制层次模型中的截距及其在点估计周围的误差。下面使用名为Dyestuff的lme4包中的内置数据,给出了lmer和qqmath函数的一个示例。代码将使用ggmath函数生成分层模型和一个漂亮的图。
library("lme4")
data(package = "lme4")
# Dyestuff
# a balanced one-way classiï¬cation of Yield
# from samples produced from six Batches
summary(Dyestuff)
# Batch is an example of a random effect
# Fit 1-way random effects linear model
fit1 <- lmer(Yield ~ 1 + (1|Batch), Dyestuff)
summary(fit1)
coef(fit1) #intercept for each level in Batch
# qqplot of the random effects with their variances
qqmath(ranef(fit1, postVar = TRUE), strip = FALSE)$Batch
最后一行代码产生了每个截距的非常好的图,每个估计周围都有误差。但格式化qqmath函数似乎非常困难,而且我一直在努力格式化情节。我想出了一些我无法回答的问题,我认为如果他们使用lmer / qqmath组合,其他人也可以从中受益:
到目前为止,在qqmath函数中添加任何其他选项会产生错误,如果它是标准图,我就不会出错。所以我很茫然。
另外,如果你觉得有一个更好的包装/功能来绘制来自lmer输出的拦截,我很乐意听到它! (例如,你能用dotplot做点1-3吗?)
感谢。
编辑:如果可以合理格式化,我也会接受替代的dotplot。我只是喜欢ggmath情节的外观,所以我开始提出一个问题。
答案 0 :(得分:38)
qqmath.ranef.mer()
和dotplot.ranef.mer()
。除了Didzis的答案,它还处理具有多个相关随机效应的模型(如qqmath()
和dotplot()
)。与qqmath()
的比较:
require(lme4) ## for lmer(), sleepstudy
require(lattice) ## for dotplot()
fit <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy)
ggCaterpillar(ranef(fit, condVar=TRUE)) ## using ggplot2
qqmath(ranef(fit, condVar=TRUE)) ## for comparison
与dotplot()
的比较:
ggCaterpillar(ranef(fit, condVar=TRUE), QQ=FALSE)
dotplot(ranef(fit, condVar=TRUE))
有时,为随机效应设置不同的比例可能是有用的 - dotplot()
强制执行。当我试图放松这个时,我不得不改变刻面(见answer)。
ggCaterpillar(ranef(fit, condVar=TRUE), QQ=FALSE, likeDotplot=FALSE)
## re = object of class ranef.mer
ggCaterpillar <- function(re, QQ=TRUE, likeDotplot=TRUE) {
require(ggplot2)
f <- function(x) {
pv <- attr(x, "postVar")
cols <- 1:(dim(pv)[1])
se <- unlist(lapply(cols, function(i) sqrt(pv[i, i, ])))
ord <- unlist(lapply(x, order)) + rep((0:(ncol(x) - 1)) * nrow(x), each=nrow(x))
pDf <- data.frame(y=unlist(x)[ord],
ci=1.96*se[ord],
nQQ=rep(qnorm(ppoints(nrow(x))), ncol(x)),
ID=factor(rep(rownames(x), ncol(x))[ord], levels=rownames(x)[ord]),
ind=gl(ncol(x), nrow(x), labels=names(x)))
if(QQ) { ## normal QQ-plot
p <- ggplot(pDf, aes(nQQ, y))
p <- p + facet_wrap(~ ind, scales="free")
p <- p + xlab("Standard normal quantiles") + ylab("Random effect quantiles")
} else { ## caterpillar dotplot
p <- ggplot(pDf, aes(ID, y)) + coord_flip()
if(likeDotplot) { ## imitate dotplot() -> same scales for random effects
p <- p + facet_wrap(~ ind)
} else { ## different scales for random effects
p <- p + facet_grid(ind ~ ., scales="free_y")
}
p <- p + xlab("Levels") + ylab("Random effects")
}
p <- p + theme(legend.position="none")
p <- p + geom_hline(yintercept=0)
p <- p + geom_errorbar(aes(ymin=y-ci, ymax=y+ci), width=0, colour="black")
p <- p + geom_point(aes(size=1.2), colour="blue")
return(p)
}
lapply(re, f)
}
答案 1 :(得分:36)
一种可能性是使用库ggplot2
绘制类似的图形,然后您可以调整绘图的外观。
首先,ranef
对象保存为randoms
。然后截距的方差保存在对象qq
中。
randoms<-ranef(fit1, postVar = TRUE)
qq <- attr(ranef(fit1, postVar = TRUE)[[1]], "postVar")
对象rand.interc
只包含具有关卡名称的随机拦截。
rand.interc<-randoms$Batch
所有对象都放在一个数据框中。对于错误间隔,sd.interc
计算为2倍平方根方差。
df<-data.frame(Intercepts=randoms$Batch[,1],
sd.interc=2*sqrt(qq[,,1:length(qq)]),
lev.names=rownames(rand.interc))
如果您需要根据值在图中排序拦截,则应重新排序lev.names
。如果拦截应按级别名称排序,则可以跳过此行。
df$lev.names<-factor(df$lev.names,levels=df$lev.names[order(df$Intercepts)])
此代码生成绘图。现在,根据因子水平,点数将相差shape
。
library(ggplot2)
p <- ggplot(df,aes(lev.names,Intercepts,shape=lev.names))
#Added horizontal line at y=0, error bars to points and points with size two
p <- p + geom_hline(yintercept=0) +geom_errorbar(aes(ymin=Intercepts-sd.interc, ymax=Intercepts+sd.interc), width=0,color="black") + geom_point(aes(size=2))
#Removed legends and with scale_shape_manual point shapes set to 1 and 16
p <- p + guides(size=FALSE,shape=FALSE) + scale_shape_manual(values=c(1,1,1,16,16,16))
#Changed appearance of plot (black and white theme) and x and y axis labels
p <- p + theme_bw() + xlab("Levels") + ylab("")
#Final adjustments of plot
p <- p + theme(axis.text.x=element_text(size=rel(1.2)),
axis.title.x=element_text(size=rel(1.3)),
axis.text.y=element_text(size=rel(1.2)),
panel.grid.minor=element_blank(),
panel.grid.major.x=element_blank())
#To put levels on y axis you just need to use coord_flip()
p <- p+ coord_flip()
print(p)
答案 2 :(得分:15)
另一种方法是从每个随机效应的分布中提取模拟值并绘制这些值。使用merTools
包,可以轻松地从lmer
或glmer
对象获取模拟,并绘制它们。
library(lme4); library(merTools) ## for lmer(), sleepstudy
fit <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy)
randoms <- REsim(fit, n.sims = 500)
randoms
现在是一个对象,如下所示:
head(randoms)
groupFctr groupID term mean median sd
1 Subject 308 (Intercept) 3.083375 2.214805 14.79050
2 Subject 309 (Intercept) -39.382557 -38.607697 12.68987
3 Subject 310 (Intercept) -37.314979 -38.107747 12.53729
4 Subject 330 (Intercept) 22.234687 21.048882 11.51082
5 Subject 331 (Intercept) 21.418040 21.122913 13.17926
6 Subject 332 (Intercept) 11.371621 12.238580 12.65172
它提供了分组因子的名称,我们获得估计的因子的级别,模型中的术语,以及模拟值的均值,中位数和标准差。我们可以使用它来生成类似于上面的毛虫图:
plotREsim(randoms)
产生:
一个很好的特性是具有不重叠零的置信区间的值以黑色突出显示。您可以使用level
参数plotREsim
来修改间隔的宽度,根据您的需要制作更宽或更窄的置信区间。
答案 3 :(得分:1)
获得所需图形的另一种方法是通过集成在plot_model()
软件包中的sjPlot
命令。优点是该命令返回一个ggplot
对象,因此有许多选项可以根据需要调整图形。我将示例保持简单,因为有许多选项可以使可视化个性化-只需检查?plot_model
中的所有选项即可。
library(lme4)
library(sjPlot)
#?plot_model
data(Dyestuff, package = "lme4")
summary(Dyestuff)
fit1 <- lmer(Yield ~ 1 + (1|Batch), Dyestuff)
summary(fit1)
plot_model(fit1, type="re",
vline.color="#A9A9A9", dot.size=1.5,
show.values=T, value.offset=.2)