From 48cba4975a7ed2b357ebd3e8b4378fb39592d28d Mon Sep 17 00:00:00 2001 From: Christian Roever <christian.roever@med.uni-goettingen.de> Date: Fri, 20 Aug 2021 17:04:32 +0200 Subject: [PATCH] re-introduced 'traceplot.bmr()' function --- NAMESPACE | 1 + R/bmr.R | 126 +++++++++++++++++++++++++++++++++++++ man/traceplot.bayesmeta.Rd | 7 ++- 3 files changed, 132 insertions(+), 2 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 80b0b3a..9796f0d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -39,6 +39,7 @@ S3method(summary, bmr) S3method(plot, bmr) S3method(pairs, bmr) S3method(forestplot, bmr) +S3method(traceplot, bmr) importFrom("grDevices", "grey", "rainbow", "rgb") diff --git a/R/bmr.R b/R/bmr.R index 12f55cb..0577e7f 100644 --- a/R/bmr.R +++ b/R/bmr.R @@ -2097,3 +2097,129 @@ forestplot.bmr <- function(x, "labeltext" = labeltext, "forestplot" = fp)) } + + + +traceplot.bmr <- function(x, mulim, taulim, ci=FALSE, + rightmargin=8, col=rainbow(x$k), ...) +{ + stopifnot(missing(mulim) || (length(mulim) == 2), + missing(taulim) || (length(taulim) <= 2), + rightmargin >= 0, length(col) == x$k) + q975 <- qnorm(0.975) + gridcol <- "grey85" + # convert "taulim" and "mulim" arguments + # to eventual "taurange" and "murange" vectors: + if (!missing(taulim) && all(is.finite(taulim))) { + if ((length(taulim)==2) && (taulim[1]>=0) && (taulim[2]>taulim[1])) + taurange <- taulim + else if ((length(taulim)==1) && (taulim>0)) + taurange <- c(0, taulim) + else + taurange <- c(0, x$qposterior(tau=0.995)*1.1) + } else { + taurange <- c(0, x$qposterior(tau=0.995)*1.1) + } + vertlines <- pretty(taurange) + if (!missing(mulim) && (all(is.finite(mulim)) && (mulim[1] < mulim[2]))) { + murange <- mulim + } else { + cm <- matrix(NA_real_, nrow=x$k, ncol=2, + dimnames=list("study"=x$labels, "moments"=c("mean", "sd"))) + for (i in 1:x$k) + cm[i,] <- x$shrink.moments(tau=taurange[2], which=i) + if (ci){ + murange <- range(c(cm[,"mean"]-q975*cm[,"sd"], cm[,"mean"]+q975*cm[,"sd"])) + } else { + murange <- range(cm[,"mean"]) + } + murange <- murange + c(-1,1)*diff(murange)*0.05 + } + + mutrace <- function(x) + { + # range of tau values: + tau <- seq(max(c(0,taurange[1]-0.1*diff(taurange))), + taurange[2]+0.1*diff(taurange), le=200) + cm.indiv <- array(NA_real_, dim=c(length(tau), 2, x$k), + dimnames=list(NULL, c("mean", "sd"), x$labels)) + for (i in 1:x$k) { + cm.indiv[,,i] <- x$shrink.moment(tau=tau, which=i) + } + plot(taurange, murange, + type="n", axes=FALSE, xlab="", ylab="effect", main="", ...) + abline(v=vertlines, col=gridcol) + abline(h=pretty(murange), col=gridcol) + abline(v=0, col=grey(0.40)) + # grey shading: + if (ci) { + for (i in 1:x$k) { + polygon(c(tau, rev(tau)), + c(cm.indiv[,"mean",i] - q975*cm.indiv[,"sd",i], + rev(cm.indiv[,"mean",i] + q975*cm.indiv[,"sd",i])), + col=grey(0.75, alpha=0.25), border=NA) + } + } + # individual estimates: + matlines(tau, cm.indiv[,"mean",], col=col, lty=1) + if (ci) { + matlines(tau, cm.indiv[,"mean",]-q975*cm.indiv[,"sd",], col=col, lty=3) + matlines(tau, cm.indiv[,"mean",]+q975*cm.indiv[,"sd",], col=col, lty=3) + } + axis(2) + for (i in 1:x$k) + axis(side=4, at=cm.indiv[length(tau),"mean",i], + labels=x$labels[i], tick=FALSE, + col.axis=col[i], las=1) + invisible() + } + + taumarginal <- function(x) + # NB: function is (essentially) identical to the one within "plot.bayesmeta()" + { + # range of tau values: + tau <- seq(max(c(0,taurange[1]-0.1*diff(taurange))), + taurange[2]+0.1*diff(taurange), le=200) + # corresponding posterior density: + dens <- x$dposterior(tau=tau) + # empty plot: + maxdens <- max(dens[is.finite(dens)],na.rm=TRUE) + plot(c(taurange[1],taurange[2]), c(0,maxdens), + type="n", axes=FALSE, xlab="", ylab="", main="") + abline(v=vertlines, col=gridcol) + # "fix" diverging density: + dens[!is.finite(dens)] <- 10*maxdens + # light grey shaded contour for density across whole range: + polygon(c(0,tau,max(tau)), c(0,dens,0), border=NA, col=grey(0.90)) + # dark grey shaded contour for density within 95% bounds: + indi <- ((tau>=x$summary["95% lower","tau"]) & (tau<=x$summary["95% upper","tau"])) + polygon(c(rep(x$summary["95% lower","tau"],2), tau[indi], rep(x$summary["95% upper","tau"],2)), + c(0, min(c(x$dposterior(tau=x$summary["95% lower","tau"]), 10*maxdens)), + dens[indi], x$dposterior(tau=x$summary["95% upper","tau"]), 0), + border=NA, col=grey(0.80)) + # vertical line at posterior median: + lines(rep(x$summary["median","tau"],2), c(0,x$dposterior(tau=x$summary["median","tau"])), col=grey(0.6)) + # actual density line: + lines(tau, dens, col="black") + # x-axis, y-axis: + abline(h=0, v=0, col=grey(0.40)) + # add axes, labels, bounding box, ... + mtext(side=1, line=par("mgp")[1], expression("heterogeneity "*tau)) + #mtext(side=2, line=par("mgp")[2], expression("marginal posterior density")) + axis(1)#; box() + invisible() + } + + # make sure to re-set graphical parameters later: + prevpar <- par(no.readonly=TRUE) + on.exit(par(prevpar)) + # generate actual plot: + graphics::layout(rbind(1,2), heights=c(2,1)) + par(mar=c(-0.1,3,0,rightmargin)+0.1, mgp=c(2.0, 0.8, 0)) + mutrace(x) + par(mar=c(3,3,-0.1,rightmargin)+0.1) + taumarginal(x) + graphics::layout(1) + par(mar=c(5,4,4,2)+0.1) + invisible() +} diff --git a/man/traceplot.bayesmeta.Rd b/man/traceplot.bayesmeta.Rd index 74ecb3f..99abbc5 100644 --- a/man/traceplot.bayesmeta.Rd +++ b/man/traceplot.bayesmeta.Rd @@ -2,6 +2,7 @@ \alias{traceplot} \alias{traceplot.default} \alias{traceplot.bayesmeta} +\alias{traceplot.bmr} \title{ Illustrate conditional means of overall effect as well as study-specific estimates as a function of heterogeneity. @@ -15,10 +16,12 @@ traceplot(x, ...) \method{traceplot}{bayesmeta}(x, mulim, taulim, ci=FALSE, rightmargin=8, col=rainbow(x$k), ...) + \method{traceplot}{bmr}(x, mulim, taulim, ci=FALSE, + rightmargin=8, col=rainbow(x$k), ...) } \arguments{ \item{x}{ - a \code{\link{bayesmeta}} object. + a \code{\link{bayesmeta}} or \code{\link{bmr}}object. } \item{mulim, taulim}{(optional) ranges for the effect (mu) and heterogeneity (tau) axes. If only one value is given for @@ -75,7 +78,7 @@ \doi{10.3102/10769986006004377}. } \seealso{ - \code{\link{bayesmeta}}. + \code{\link{bayesmeta}}, \code{\link{bmr}}. } \examples{ # load example data: -- GitLab