bayestestR turns posterior draws into a consistent set of indices
:ghost: Utilities for analyzing Bayesian models and posterior distributions
At a glance
- What is it?
- bayestestR is an R package in the easystats family that reads a fitted Bayesian model and reports four families of indices over its posterior, including probability of direction, ROPE probabilities and Bayes factors, so that effects are described the same way across model objects.
- Who is it for?
- bayestestR fits a researcher who has fitted a Bayesian model in rstanarm, brms or BayesFactor and needs a defensible, consistent description of what the posterior says, rather than a hand-computed set of numbers that differ between laboratories. It is the wrong choice if you work outside the Bayesian framework, and it is the wrong choice if you want one number, because the package exists precisely to give you a range of indices that have to be interpreted against each other.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly R, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap between a posterior and a summary table
The README states the problem in one line. Existing R packages allow users to fit a large variety of models and extract and visualize the posterior draws, but most of these packages only return a limited set of indices, for example point estimates and confidence intervals. bayestestR provides a comprehensive and consistent set of functions to analyse and describe posterior distributions generated by a variety of model objects, including popular modelling packages such as rstanarm, brms and BayesFactor.
The word consistent is doing the work. The problem with a hand-rolled summary is not that it is hard to compute, it is that different people compute different things. One report states the median and a 90 percent equal-tailed interval, another states the MAP and a highest density interval, a third states a Bayes factor against the null. Each is defensible, and none is comparable with the other without going back to the code.
The package is part of the easystats family, and the README recommends using library(easystats) rather than loading bayestestR directly, which makes all features of the easystats ecosystem available. There is also easystats::install_latest() to stay updated.
For the audience, the target is a researcher who already has a fitted model object and wants to describe its posterior in a way that is standard, reproducible and citable. It is a reporting layer, not a modelling layer, and that division is the right frame for judging it.
Four families of index, and what each one answers
In the Bayesian framework, parameters are estimated as distributions, and the README organises the indices into four groups that correspond to four questions.
Centrality is the first, and it is the most familiar. The mean, the median or map_estimate() for an estimation of the mode give the location of the posterior, and point_estimate() can be used to get them at once and can be run directly on models. The emphasis on the MAP as an option matters, because the mode and the median of a skewed posterior can differ enough to change the conclusion of a study.
Uncertainty is the second group. hdi() gives Highest Density Intervals, with hdi(method = "density") for Shortest Probability Intervals, and eti() gives Equal-Tailed Intervals. ci() is the general method for both confidence and credible intervals.
The third group is Effect Existence, which is whether an effect is different from zero. The fourth is Effect Significance, which is whether the effect size can be considered non-negligible. That distinction is the conceptual core of the package, and separating existence from significance is what allows a result to be described as small but clearly non-zero, or large but practically irrelevant.
The four groups together give a fuller description than the point estimate and interval that the README says other packages return, and each index has its own article in the documentation.
Existence: p_direction, p_pointnull and bf_pointnull
The existence indices are the part of the package that most changes how a result is written up, because they are Bayesian analogues of quantities that frequentist workflows report as a p-value.
p_direction() is described as a Bayesian equivalent of the frequentist p-value, and the README points to Makowski and colleagues from 2019 for the argument behind it. The quantity is the probability that the effect has a particular sign, taking the null value into account, which is why it is not simply half of the probability mass above zero.
p_pointnull() represents the odds of the null hypothesis, h0 = 0, compared to the most likely hypothesis, which is the MAP. That is a different question again, and it is the one that gets confused with a p-value most often, because both are described as a comparison against the null but they are not the same comparison.
bf_pointnull() is the classic Bayes Factor assessing the likelihood of effect presence against its absence, again with h0 = 0 as the null.
So three functions, three different comparisons against zero, and a user who reaches for the wrong one will produce a number that looks right and means something else. The documentation has separate articles for these indices and for their comparison, and those articles are the right place to check the semantics before writing the results section.
The Bayes factor route has a further wrinkle, because Bayes factors require the priors of both models to be stated, and the README points to a dedicated article on Bayes factors as well as a comparison of point estimates, which is a comparison the package performs for you.
Significance: the ROPE and p_significance
The significance group answers whether the effect is big enough to matter in practice, and it does so through the Region of Practical Equivalence.
p_rope() is the probability of the effect falling inside a Region of Practical Equivalence. The ROPE is a band of values around the null that you have declared to be practically indistinguishable from it, and the probability of the posterior falling inside that band is a direct statement about how plausible a negligible effect is. The converse, the probability of falling outside the ROPE, is the probability that the effect is at least practically distinguishable from zero.
bf_rope() computes a Bayes factor against the null as defined by a region, the ROPE, which is the Bayes factor version of the same question and inherits the same requirement that the region be stated.
p_significance() combines a region with something else, and here the README text in hand is cut off partway through the sentence describing it. The available text says that p_significance() combines a region of, and then stops. That is worth flagging rather than papering over, because the index name suggests it is a combined measure of significance and the exact combination is precisely the thing a reader needs to know before quoting the number. The feature reference index in the documentation is the place to get the full description.
The choice of ROPE width is the practical decision here, and it is a modelling judgement rather than a software one. A ROPE that is too wide makes every effect look negligible, and one that is too narrow makes everything look significant, so the width has to come from the domain, not from habit.
Intervals: HDI, ETI and the density method
The uncertainty functions are where the package is most opinionated, and the opinion is worth understanding.
hdi() returns the Highest Density Interval, which is the narrowest interval containing a given share of the posterior mass. For a skewed or multimodal posterior, that interval is not centred on the median, and for a multimodal posterior it can even be discontinuous, because it keeps whichever regions carry the highest density.
The method argument matters more here than in most packages. With hdi(method = "density") you get a Shortest Probability Interval instead, which is computed differently and will not always coincide with the classic HDI. The distinction is not cosmetic, because a table that says 90 percent HDI and a table that says 90 percent SPI are describing different intervals, and readers will not know that from the number alone.
eti() returns the Equal-Tailed Interval, which puts the same mass in each tail, which makes its bounds directly comparable with the equal-tailed intervals that frequentist packages report, at the cost of being less informative under skew than the HDI.
ci() is the general entry point for both confidence and credible intervals, and it is the function to reach for when the code needs to branch on which kind of interval is wanted rather than hard-coding one.
Installing from CRAN, and the easystats umbrella
The package is on CRAN, and the latest development version is on R-universe from rOpenSci. The README gives both commands in a table:
| Release | CRAN | `install.packages("bayestestR")` |
| Development | R-universe | `install.packages("bayestestR", repos = "https://easystats.r-universe.dev")` |Once installed, the package is loaded the usual way:
library("bayestestR")The README's tip is to use library(easystats) instead, which makes all features of the easystats ecosystem available, and to use easystats::install_latest() to stay updated. The r-universe badge and the status badge in the README are there to signal which build you are running, which matters in a package that changes its index definitions between minor versions.
The documentation is unusually well organised for a package this size, and it is the part of the project that most justifies the effort. There are tutorials for getting started with Bayesian analysis, an initiation to Bayesian models, a confirmation of Bayesian skills and a route to becoming what the README calls a Bayesian master, and then a set of article pages on credible intervals, probability of direction, the region of practical equivalence, Bayes factors, a comparison of point estimates, a comparison of the indices of effect existence, and reporting guidelines.
That last one is the article to read first if you are writing a paper, because it is the one that tells you which indices to report and which to leave out.
Model coverage, licence and release pace
The package works with model objects from rstanarm, brms and BayesFactor, and the topic list names the concepts it exposes: Bayes factors, credible intervals, the highest density interval, the MAP, the region of practical equivalence and posterior distributions generally. The name and the easystats affiliation are the reason to look at it even if you have never used the package, because it is one of the pieces that makes a Bayesian analysis in R reportable.
The licence is GPL-3.0, with the licence file at the root of the repository. For a package that is loaded into an analysis rather than distributed, that is a normal choice, though an organisation with a policy on GPL in the dependency tree should note it, since GPL-3.0 is a copyleft licence and the package is not something you can vendor into a closed product without obligations. This is a description of the licence terms rather than legal advice.
The releases are frequent. Version 0.20.0 came out on 2026-10-16, 0.19.0 on 2026-09-09 and 0.18.1 on 2026-05-24, and the last push to the repository was on 2026-10-19. A package that releases every few weeks and changes index behaviour between versions needs pinning in a project that has to be reproducible, and the NEWS.md file at the root is the changelog to read when you upgrade.
The repository layout is a well-maintained R package: DESCRIPTION and NAMESPACE, an R directory for the code, man for the documentation, tests, vignettes, a revdep directory for reverse dependency checks, a paper directory, cran-comments.md for the CRAN submission notes, and a .lintr configuration alongside a NEWS.md and an R project file. There is also a WIP directory and a GEMINI.md, which together with the pre-2026 tooling suggests the project uses AI assistance in its development workflow.
Editorial conclusion
bayestestR fits a researcher who has fitted a Bayesian model in rstanarm, brms or BayesFactor and needs a defensible, consistent description of what the posterior says, rather than a hand-computed set of numbers that differ between laboratories. It is the wrong choice if you work outside the Bayesian framework, and it is the wrong choice if you want one number, because the package exists precisely to give you a range of indices that have to be interpreted against each other. Before adopting it, read the reporting guidelines vignette, decide which index is appropriate for the question you are actually asking, and check the vignette for the specific index, because a probability of direction and a probability of practical equivalence answer different questions and are easy to mix up.
Frequently asked questions
What problem does bayestestR solve?
Existing R packages fit models and extract posterior draws but usually return only a limited set of indices such as point estimates and confidence intervals. bayestestR provides a comprehensive and consistent set of functions to analyse and describe posterior distributions from model objects including rstanarm, brms and BayesFactor.
How do I install bayestestR?
The release version is on CRAN and is installed with install.packages("bayestestR"). The latest development version is on R-universe, installed with install.packages("bayestestR", repos = "https://easystats.r-universe.dev"). The README suggests using library(easystats) instead of loading bayestestR on its own.
Which indices does bayestestR provide for effect existence and significance?
For effect existence there is p_direction() as a Bayesian equivalent of the frequentist p-value, p_pointnull() for the odds of the null against the MAP, and bf_pointnull() for a classic Bayes Factor against h0 = 0. For significance there is p_rope() for the probability of the effect inside a Region of Practical Equivalence, bf_rope() for a Bayes factor against a null defined by a region, and p_significance() which combines a region with another quantity.
What is the difference between hdi() and eti() in bayestestR?
hdi() returns Highest Density Intervals, the narrowest interval containing the given probability mass, and with the density method it returns Shortest Probability Intervals. eti() returns Equal-Tailed Intervals, which place the same mass in each tail. ci() is the general function for both confidence and credible intervals.
How should I cite bayestestR?
The README asks for the Journal of Open Source Software paper, Makowski, Ben-Shachar and Lüdecke (2019), bayestestR: Describing Effects and their Uncertainty, Existence and Significance within the Bayesian Framework, 4(40), 1541, doi 10.21105/joss.01541, and also points to the Frontiers in Psychology paper on the indices of effect existence and significance.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/easystats-bayestestr)Was this useful?