By default we use central posterior intervals. For example, the central 95% interval is the (2.5%, 97.5%) quantiles.
But sometimes the central interval doesn’t seem right. This came up recently with a coronavirus testing example, where the posterior distribution for the parameter of interest was asymmetric so that the central interval is not such a reasonable summary. See Figure 1 here: http://www.stat.columbia.edu/~gelman/research/unpublished/specificity.pdf
Instead, sometimes it can make sense to use a shortest probability interval (similar to the highest posterior density interval), as discussed in the paper with Ying Liu and Tian Zheng: http://www.stat.columbia.edu/~gelman/research/published/spin.pdf
The brute force approach to computing a shortest probability interval is to compute all the intervals of specified coverage and take the shortest. For example, if you have 1000 simulation draws and you want the 95% interval for a particular quantity of interest, z, you sort the 1000 simulations of z, compute 50 intervals, (z_1, z_951), (z_2, z_952), …, (z_50, z_1000), and you take the interval that’s the shortest.
There’s one additional twist: if the quantity of interest is bounded, you want to allow the possibility of the interval to go all the way to the boundary. So if there’s a lower bound a and an upper bound b, you also consider the intervals, (a, z_950) and (z_51, b) as candidates.
Here’s R code:
spin <- function(x, lower=NULL, upper=NULL, conf=0.95){
x <- sort(as.vector(x))
if (!is.null(lower)) {
if (lower > min(x)) stop("lower bound is not lower than all the data")
else x <- c(lower, x)
}
if (!is.null(upper)) {
if (upper < max(x)) stop("upper bound is not higher than all the data")
else x <- c(x, upper)
}
n <- length(x)
gap <- round(conf*n)
width <- x[(gap+1):n] - x[1:(n-gap)]
index <- min(which(width==min(width)))
x[c(index, index + gap)]
}
This particular code is kinda hacky in that it does not account for fencepost errors, but it conveys the general idea.
It works! But there is a concern that the procedure has unnecessary Monte Carlo error, in that we’re computing the minimum width of these empirical intervals. It seems like some smoothing should improve things.
In the above-linked Liu et al. paper, we present a pretty complicated procedure to compute a shortest probability interval efficiently. It works well in the paper, but I don’t really trust it in general. I think we should have something more transparent and reliable.
The short version of this post is that it would be good to have the shortest posterior interval as an option, not for Stan’s automatic output–I think by default the central interval is fine–but as an available option when users want it because it does come up.
The longer version is that I think there’s a research opportunity to come up with a more efficient shortest posterior interval computation that’s also clean and robust.
EDIT: @maxbiostat added code identation.