Pergunta

I often run JAGS models on simulated data with known parameters. I like the default plot method for mcmc objects. However, I would like to add an abline(v=TRUE_VALUE) for each parameter that is modelled. This would give me a quick check for whether the posterior is reasonable.

Of course I could do this manually, or presumably reinvent the wheel and write my own function. But I was wondering if there is an elegant way that builds on the existing plot method.

Here's a worked example:

require(rjags)
require(coda)

# simulatee data
set.seed(4444)
N <- 100 
Mu <- 100
Sigma <- 15
y <- rnorm(n=N, mean=Mu, sd=Sigma)
jagsdata <- list(y=y)

jags.script <- "
model {
    for (i in 1:length(y)) {
        y[i]  ~ dnorm(mu, tau)
    }
    mu  ~ dnorm(0, 0.001)    
    sigma ~ dunif(0, 1000)
    tau <- 1/sigma^2
}"


mod1 <- jags.model(textConnection(jags.script), data=jagsdata, n.chains=4, 
                   n.adapt=1000)
update(mod1, 200) # burn in
mod1.samples <- coda.samples(model=mod1,
                             variable.names=c('mu', 'sigma'),
                             n.iter=1000)                  
plot(mod1.samples)

enter image description here

I just want to run something like abline(v=100) for mu and abline(v=15) for sigma. Of course in many other examples, I would have 5, 10, 20 or more parameters of interest. Thus, I'm interested in being able to supply a vector of true values for named parameters.

I've had a look at getAnywhere(plot.mcmc). Would modifying that be a good way to go?

Foi útil?

Solução

Okay. So I modified plot.mcmc to look like this:

my.plot.mcmc <- function (x, trace = TRUE, density = TRUE, smooth = FALSE, bwf, 
    auto.layout = TRUE, ask = FALSE, parameters, ...) 
{
    oldpar <- NULL
    on.exit(par(oldpar))
    if (auto.layout) {
        mfrow <- coda:::set.mfrow(Nchains = nchain(x), Nparms = nvar(x), 
            nplots = trace + density)
        oldpar <- par(mfrow = mfrow)
    }
    for (i in 1:nvar(x)) {
        y <- mcmc(as.matrix(x)[, i, drop = FALSE], start(x), 
            end(x), thin(x))
        if (trace) 
            traceplot(y, smooth = smooth, ...)
        if (density) {
            if (missing(bwf)) {
                densplot(y, ...); abline(v=parameters[i])
            } else densplot(y, bwf = bwf, ...)
        }
        if (i == 1) 
            oldpar <- c(oldpar, par(ask = ask))
    }
}

Then running the command

my.plot.mcmc(mod1.samples, parameters=c(Mu, Sigma))

produces this

enter image description here

Note that parameters must be a vector of values in the same sort order as JAGS sorts variables, which seems to be alphabetically and then numerically for vectors.

Lessons learnt

  • Simply writing a new plot.mcmc didn't work by default presumably because of namespaces. So I just created a new function
  • I had to change set.mfrow to coda:::set.mfrow presumably also because of namespaces.
  • I changed ask to ask=FALSE, because RStudio permits browsing through figures.

I'd be happy to hear any suggestions about better ways of overriding or adapting existing S3 methods.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top