Ich hatte großartige Erfahrungen, um Hilfe hier zu fragen, und ich hoffe, wieder Hilfe zu bekommen.Ein Raupe-Plot von nur den "signifikanten" Zufallseffekten aus einem Mixed-Effects-Modell
Ich schätze ein ziemlich großes Mixed-Effekt-Modell, in dem einer der zufälligen Effekte über 150 verschiedene Ebenen hat. Das würde ein Standard-Raupe-Plot ziemlich unlesbar machen.
Ich möchte, wenn alles möglich ist, eine Raupe Handlung von nur den Ebenen des zufälligen Effekts, die für einen Mangel an besseren Begriff "signifikant" sind. Das heißt: Ich möchte ein Raupe-Diagramm, in dem entweder der zufällige Schnittpunkt oder die zufällige Steigung für einen variierenden Koeffizienten ein "Konfidenzintervall" hat (ich weiß, dass es nicht ganz das ist), das null nicht enthält.
Betrachten Sie dieses Standardmodell aus den sleepstudy
Daten, die standardmäßig mit lme4
sind.
library(lme4)
fit <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy)
ggCaterpillar(ranef(fit,condVar=TRUE), QQ=FALSE, likeDotplot=TRUE, reorder=FALSE)[["Subject"]]
Ich würde diese Raupe Plot bekommen.
Die Raupe Grundstück Ich benutze kommt aus this code. Beachten Sie, dass ich dazu tendiere, weniger konservative Grenzen für die Intervalle zu verwenden (d. H. 1,645 * se und nicht 1,96 * se).
Grundsätzlich mag ich eine Raupe Handlung, die die Ebene nur einschließen würde für 308, 309, 310, 330, 331, 335, 337, 349, 350, 352 und 370, da diese Werte entweder abfängt hatten oder Pisten wessen Intervalle nicht Null enthalten. Ich frage, weil mein Raupe-Plot von über 150 verschiedenen Ebenen irgendwie unlesbar ist und ich denke, dass dies eine sinnvolle Lösung sein könnte.
Nachführbarer Code folgt. Ich schätze wirklich jede Hilfe.
# https://stackoverflow.com/questions/34120578/how-can-i-sort-random-effects-by-value-of-the-random-effect-not-the-intercept
ggCaterpillar <- function(re, QQ=TRUE, likeDotplot=TRUE, reorder=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, ])))
if (reorder) {
ord <- unlist(lapply(x, order)) + rep((0:(ncol(x) - 1)) * nrow(x), each=nrow(x))
pDf <- data.frame(y=unlist(x)[ord],
ci=1.645*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)))
} else {
pDf <- data.frame(y=unlist(x),
ci=1.645*se,
nQQ=rep(qnorm(ppoints(nrow(x))), ncol(x)),
ID=factor(rep(rownames(x), ncol(x)), levels=rownames(x)),
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 of the Random Effect") + ylab("Random Effect")
}
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)
}
library(lme4)
fit <- lmer(Reaction ~ Days + (Days|Subject), sleepstudy)
ggCaterpillar(ranef(fit,condVar=TRUE), QQ=FALSE, likeDotplot=TRUE, reorder=FALSE)[["Subject"]]
ggsave(file="sleepstudy.png")
"Ich landete ein wenig weggetragen bekommen ..." Heh, heh. Du machst keinen Spaß. Tolle Antwort! – eipi10
Heh, ich habe die 'lme4' Message Boards lange genug gelesen, um besser zu wissen, als ernsthaft" Konfidenzintervalle "und" signifikant "im Kontext von zufälligen Effekten zu verwenden. : P Und das war eine ausgezeichnete Antwort. Ich wusste auch nichts über das "Besen" -Paket. Danke noch einmal! – steve
Ben das ist großartig! Würde es Ihnen etwas ausmachen, wenn ich es Ihren vielen Besenbeiträgen hinzufügen würde? –