The ability to implement statistical models in the BUGS language facilitates Bayesian inference by automating MCMC algorithms. Software packages that interpret the BUGS language include OpenBUGS, WinBUGS, and JAGS. R packages that link BUGS software to the R environment, including rjags and R2WinBUGS, are widely used in Bayesian analysis. Indeed, many packages in the Bayesian task view on CRAN (http://cran.r-project.org/web/views/Bayesian.html) depend on this integration. However, the R and BUGS languages use different representations of common probability density functions, creating a potential for errors to occur in the implementation or interpretation of analyses that use both languages. Here we review different parameterizations used by the R and BUGS languages, describe how to translate between the languages, and provide an R function, r2bugs.distributions
, that transforms parameterizations from R to BUGS and back again.
Distribution | Lang. | Parameterization | Use | Notes | |
Normal | |||||
R | \(\frac{1}{\sqrt{2 \pi}\sigma}\exp\left(-\frac{\left(x - \mu\right)^2}{2 \sigma^2}\right)\) | dnorm( \(x\), mean = \(\mu\), sd = \(\sigma\)) |
|||
BUGS | \(\sqrt{\frac{\tau}{2\pi}}\exp\left(-\left(x-\mu\right)^2\tau\right)\) | dnorm(mean = \(\mu\), precision = \(\tau\)) |
\(\tau=\left(\frac{1}{\sigma}\right)^2\) | ||
log-Normal | |||||
R | \(\frac{1}{\sqrt{2 \pi} \sigma x} \exp\left(-\frac{\left(\textrm{log}\left(x\right) - \mu\right)^2}{\left(2 \sigma^2\right)}\right)\) | dlnorm( \(x\), mean = \(\mu\), sd = \(\sigma\)) |
|||
BUGS | \(\frac{\sqrt{\tau}}{x}\exp\left(\frac{-\tau\left(\textrm{log}\left(x\right)-\mu\right)^2}{2}\right)\) | dlnorm(mean = \(\mu\), precision = \(\tau\)) |
\(\tau=\left(\frac{1}{\sigma}\right)^2\) | ||
Binomial | reverse parameter order | ||||
R | \({n \choose x} p^{x}\left(1-p\right)^{n-x}\) | dbinom( \(x\), size = \(n\), prob = \(p\)) |
|||
BUGS | same | dbin(prob = \(p\), size = \(n\)) |
|||
Negative Binomial | reverse parameter order | ||||
R | \(\frac{\Gamma\left(x+n\right)}{\Gamma\left(n\right) x!} p^n \left(1-p\right)^x\) | dnbinom( \(x\), size = \(n\), prob = \(p\)) |
size (n ) is continuous |
||
BUGS | \({x+r-1 \choose x}p^r\left(1-p\right)^x\) | dnegbin(prob = \(p\), size = \(r\)) |
size (r ) is discrete |
||
Weibull | |||||
R | \(\frac{a}{b} (\frac{x}{b})^{a-1} \exp\left(- \left(\frac{x}{b}\right)^a\right)\) | dweibull( \(x\), shape = \(a\), scale = \(b\)) |
|||
BUGS | \(\nu\lambda x^{\nu - 1}\exp\left(-\lambda x^{\nu}\right)\) | dweib(shape = \(\nu\), lambda = \(\lambda\)) |
\(\lambda=\left(\frac{1}{b}\right)^a\) | ||
Gamma | reverse parameter order | ||||
R | \({\frac{r^a}{\Gamma(a)}} x^{a-1} \exp(-xr)\) | dgamma( \(x\), shape = \(a\), rate = \(r\)) |
|||
BUGS | \({\frac{\lambda^r x^{r-1}\exp(-\lambda x)}{\Gamma(r)}}\) | dgamma(shape = \(r\), lambda = \(\lambda\)) |
R and BUGS implement many of the same probability distribution functions, but they often parameterize the same distribution differently (Table 1). Although these probability distribution functions are clearly described in the documentation of their respective languages, we were unable to find a summary of these differences in one place. The motivation for this article is to document and clarify these differences. Our sources are the JAGS documentation (Plummer 2010) and the documentation of individual R functions.
To support the automation of model specification in JAGS with priors
computed and stored in R (LeBauer et al. 2013), we developed a function to
translate parameterizations of common probability distributions from R
to BUGS (and back again, by specifying direction = ’bugs2r’
).
Parameter transformations, parameter order, and differences in function
names are documented in Table 1 and
implemented in the R function r2bugs.distributions
.
<- function(priors, direction = 'r2bugs') {
r2bugs.distributions $distn <- as.character(priors$distn)
priors$parama <- as.numeric(priors$parama)
priors$paramb <- as.numeric(priors$paramb)
priors## index dataframe according to distribution
<- priors$distn %in% c('norm', 'lnorm') # these have same transform
norm <- grepl("weib", priors$distn) # matches r and bugs version
weib <- priors$distn == 'gamma'
gamma <- grepl("chisq", priors$distn) # matches r and bugs version
chsq <- priors$distn %in% c('binom', 'bin') # matches r and bugs version
bin <- priors$distn %in% c('nbinom', 'negbin') # matches r and bugs version
nbin
## Normal, log-Normal: Convert sd to precision
<- ifelse(direction == "r2bugs", -2, -0.5)
exponent $paramb[norm] <- priors$paramb[norm] ^ exponent
priors
## Weibull
if(direction == 'r2bugs'){
## Convert R parameter b to BUGS parameter lambda by l = (1/b)^a
$paramb[weib] <- (1 / priors$paramb[weib]) ^ priors$parama[weib]
priorselse if (direction == 'bugs2r') {
} ## Convert BUGS parameter lambda to BUGS parameter b by b = l^(-1/a)
$paramb[weib] <- priors$paramb[weib] ^ (- 1 / priors$parama[weib] )
priors
}
## Reverse parameter order for binomial and negative binomial
| nbin, c('parama', 'paramb')] <-
priors[bin | nbin, c('paramb', 'parama')]
priors[bin
## Translate distribution names
if(direction == "r2bugs"){
$distn[weib] <- "weib"
priors$distn[chsq] <- "chisqr"
priors$distn[bin] <- "bin"
priors$distn[nbin] <- "negbin"
priorselse if(direction == "bugs2r"){
} $distn[weib] <- "weibull"
priors$distn[chsq] <- "chisq"
priors$distn[bin] <- "binom"
priors$distn[nbin] <- "nbinom"
priors
}return(priors)
}
As an example, we take the R-parameterized prior distribution
\(X \sim \mathcal{N}(\mu=10,\sigma=2)\) and convert it to BUGS
parameterization \(X \sim \mathcal{N}(\mu=10,\tau=1/4)\). We specify a
model in JAGS that allows us to sample directly from a prior
distribution. The function works for each of the distributions in
Table 1. This particular example is the JAGS
implementation of rnorm(10000, 10, 2)
in R. It is presented as minimal
demonstration; for a non-trivial application, see (LeBauer et al. 2013).
<- data.frame(distn = "norm", parama = 10, paramb = 2)
r.distn <- r2bugs.distributions(r.distn)
bugs.distn
<- function(prior = data.frame(distn = "norm", parama = 0,
sample.bugs.distn paramb = 1), n = 10000) {
require(rjags)
<- paste0(
model.string "model{Y ~ d", prior$distn,
"(", prior$parama,
## chisqr has only one parameter
ifelse(prior$distn == "chisqr", "", paste0(", ", prior$paramb)), ");",
"a <- x}"
) ## trick JAGS into running without data
writeLines(model.string, con = "test.bug")
<- jags.model(file = "test.bug", data = list(x = 1))
j.model <- window(
mcmc.object coda.samples(
model = j.model, variable.names = c('Y'),
n.iter = n * 4, thin = 2),
start = n)
<- sample(as.matrix(mcmc.object)[,"Y"], n)
Y
}<- sample.bugs.distn(bugs.distn) X
This collaboration began on the Cross Validated statistical forum (http://stats.stackexchange.com/q/5543/1381). Funding was provided to DSL and MCD by the Energy Biosciences Institute.
Bayesian, Cluster, GraphicalModels, MixedModels
This article is converted from a Legacy LaTeX article using the texor package. The pdf version is the official version. To report a problem with the html, refer to CONTRIBUTE on the R Journal homepage.
Text and figures are licensed under Creative Commons Attribution CC BY 4.0. The figures that have been reused from other sources don't fall under this license and can be recognized by a note in their caption: "Figure from ...".
For attribution, please cite this work as
S. LeBauer, et al., "Translating Probability Density Functions: From R to BUGS and Back Again", The R Journal, 2013
BibTeX citation
@article{RJ-2013-020, author = {S. LeBauer, David and C. Dietze, Michael and M. Bolker, Benjamin}, title = {Translating Probability Density Functions: From R to BUGS and Back Again}, journal = {The R Journal}, year = {2013}, note = {https://rjournal.github.io/}, volume = {5}, issue = {1}, issn = {2073-4859}, pages = {207-209} }