# bayesian-analysis-recipes is a notebook per model, built around one argument about ANOVA

> This collection of PyMC3 notebooks is organised so that each model gets its own file, and the whole premise is that methods like ANOVA can be replaced by more interpretable Bayesian alternatives. It is a teaching cookbook rather than a library, and the notebooks are executed to build a static documentation site.

**ericmjl/bayesian-analysis-recipes** — A collection of Bayesian data analysis recipes using PyMC3

- Repository: https://github.com/ericmjl/bayesian-analysis-recipes
- Website: https://ericmjl.github.io/bayesian-analysis-recipes
- Stars: 562 · Forks: 110
- Language: Jupyter Notebook
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/ericmjl-bayesian-analysis-recipes

## One notebook per model, and the five things each one contains

The stated goal is precise enough to be a specification. My goal here is to have one notebook per model, and in each notebook you should end up finding five things.

First, the kind of problem that is being tackled. Second, a description of how the data should be structured. Third, an example data table, which will generally end up being tidy data. Fourth, PyMC3 code for the model, and in some notebooks there may be two versions of the same model. Fifth, examples on how to report findings from the MCMC-sampled posterior.

That last item is what separates this from a set of code snippets. A notebook that stops at a posterior object has moved the problem rather than solved it, and the fifth bullet is the one that says the posterior has to be turned into something a reader can act on.

The tidy data requirement is the other structural decision. Linking to Hadley Wickham's tidy data paper, the author makes the point that a standard table shape is what lets you move between models without rewriting the data handling for each one.

The two-versions allowance is worth noting too. When a notebook presents two versions of the same model, the natural reading is a contrast: a simple version that you could explain to a colleague, and a more elaborate one that answers the question properly. That is a teaching move, and it is one you rarely find in a library's own documentation.

The primary language of the repository is Jupyter Notebook, the licence is MIT, the default branch is master, and the homepage is ericmjl.github.io/bayesian-analysis-recipes. The last push was on 2026-05-16 and there are no GitHub releases.

## The thesis: that ANOVA can be replaced by something more readable

The collection is organised around an argument, and the argument is stated in the README under a heading about a hypothesis, which is itself a joke that a Bayesian audience will appreciate.

The claim follows the Pareto principle: a large fraction of real-world problems can essentially be boiled down to a few categories of problems, which have a Bayesian interpretation.

The worked example of that claim is a comparison with ANOVA. The author suggests that commonly-used methods like ANOVA can be replaced by conceptually simpler and much more interpretable Bayesian alternatives, like John Kruschke's BEST, which stands for Bayesian Estimation Supersedes the T-Test.

The reasoning is worth following because it is the pedagogical core of the whole repository. ANOVA only tests whether means of multiple treatment groups are the same or not. BEST gives the estimated posterior distribution over each of the treatment groups, assuming each treatment group is identical. From that posterior you can, given the data at hand, make statements about how any particular pair of groups differ, without requiring additional steps such as multiple hypothesis corrections.

So the argument is not that Bayesian methods are better at the same task. It is that the Bayesian formulation gives you a different kind of answer. A p-value is a decision about whether a null hypothesis should be rejected; a posterior over group differences is an estimate you can act on, and the specific pairs you care about can be read off it directly.

The topic list on the repository backs up the shape of the collection: bayesian, bayesian-analysis, bayesian-data-analysis, bayesian-inference, bayesian-methods, bayesian-statistics, neural-networks, notebook and treatment-groups. The treatment-groups topic is the ANOVA comparison in tag form.

The further reading list is curated rather than exhaustive: Bayesian Methods for Hackers and Think Bayes as books, the Kruschke paper, and four talks, including two Computational Statistics sessions at SciPy 2015 and a Bayesian Statistical Analysis with Python talk at PyCon 2017.

## The notebooks become a static site, and the build executes them

The Makefile shows how the repository is turned into documentation, and it is the part of the project that is most likely to be useful to you even if you never read the notebooks.

```makefile
htmldocs:
	jupyter nbconvert notebooks/bayesian-estimation-multi-sample.ipynb --output ../docs/bayesian-estimation-multi-sample.html
	jupyter nbconvert notebooks/dirichlet-multinomial-bayesian-proportions.ipynb --output ../docs/dirichlet-multinomial-bayesian-proportions.html
```

Each notebook is converted to HTML into a sibling docs directory. The rule at the top sets execute_params to --execute with an ExecutePreprocessor.timeout of 600, which means the notebooks are run as they are converted, with a ten minute ceiling per cell.

That detail is the point. A converted notebook whose code has not been executed shows you the inputs and the source with empty outputs. An executed one shows the numbers, the diagnostics and the plots, which is the entire reason to read a notebook rather than read the code. So the build doubles as a test: if a model no longer samples, or a dependency has moved and an API has changed, the documentation build fails rather than publishing something silently wrong.

The site itself is MkDocs. The requirements file is entirely about that, and the comment at the top of it explains why. It says the contents are used only for building static site docs on Dokku, and lists mkdocs, mkdocs-minify-plugin, pymdown-extensions, mkdocs-material and mknotebooks. The last of those is the plugin that renders Jupyter notebooks inside the MkDocs site rather than as separate HTML pages.

So there are two output paths: per-notebook HTML files for people who want one page per model, and a served MkDocs site for people who want to move through it. The docs target runs mkdocs serve for local work.

The repository also has an environment.yml, which is the usual way to pin a scientific Python stack, and a Binder badge in the README header that launches the notebooks in a hosted environment. That combination, a pinned environment plus Binder, is what makes the collection usable by someone who does not want to assemble the dependency stack themselves.

## The repository layout: models, datasets, an incubator and an abandoned CI file

The top-level entries describe a project that has grown past a flat list of notebooks, and a few of them carry more information than they appear to.

There is a models/ directory, which is where the current notebooks live, alongside datasets/ for the example data, docs/ for the generated HTML, and incubator/ for work that has not graduated. The incubator directory is the interesting one, because it is a visible staging area rather than a hidden branch, which tells you the author expects some of it to graduate and some to be abandoned, and that both outcomes are acceptable.

There is also a test_gpu.py file at the root, which suggests an attempt to check that the notebooks run on GPU hardware. That is a reasonable thing to want for a collection that includes a mixture model and a neural network topic, but the presence of a single test file rather than a test suite suggests it is a helper rather than a continuous integration check.

The .travis.yml file dates the project. Travis CI was the dominant hosted CI for Python before GitHub Actions became the default, and a repository that still carries a Travis configuration with a .pre-commit-config.yaml alongside it has a pre-Actions history. That is not a criticism of the notebooks, but it does mean the continuous integration story is old, and the Makefile, the Binder badge and the MkDocs build are what actually run.

There is an app.json at the root, which is the Heroku and Dokku deployment descriptor, consistent with the comment in the requirements file about building the static site docs on Dokku. The mkdocs.yml holds the site configuration, nbconvert_config.py holds the notebook conversion settings, and CONTRIBUTING.md and a LICENSE complete the conventional set.

One naming detail is worth flagging for anyone who tries to build this. The Makefile refers to a notebooks/ directory with a wildcard, while the top-level entries list a models/ directory. Those paths do not agree, so the htmldocs target as written will find no notebooks to convert unless the directory is arranged to match.

## Where this collection is the wrong answer

Three limits, and the first is about the version of PyMC it was written against.

The first is that the code is PyMC3, and the PyMC project has since reorganised its API substantially. The README names PyMC3 in the model-code bullet and in the repository description. A notebook written against PyMC3 will not run against a current PyMC installation without edits, and the errors will be the kind that come from renamed modules and changed sampler arguments rather than from something you can fix by reading the error message. For a learner who is going to write their own PyMC code against the current release, a cookbook pinned to the old API teaches habits that have to be unlearned. For a learner who wants to see a complete Bayesian workflow once, the API vintage does not matter much.

The second is the framing. The collection is organised one notebook per model, and that is the right structure for a reference but the wrong one for a question. If you have a specific analysis problem, you have to work out which notebook is closest to it, then adapt the data preparation, which the recipes explicitly do not cover in general, since the data-structure bullet is a description of the shape rather than a general method for reshaping your own table. There is no treatment-effects section, no missing-data handling, no measurement error, no hierarchical model over sites unless that notebook happens to be the one you need.

The third is that it is not a library. There is nothing to install and nothing to import, the package name is not a thing, and the deliverable is understanding rather than reuse. If your requirement is a stable, tested implementation of a Bayesian model you can call from production code, this is the wrong artifact entirely and the PyMC library itself is the answer.

The alternative approach, for a team that has decided to go Bayesian, is to read the two books the README recommends and then write your own model against current PyMC, using these notebooks as worked examples of the reporting step rather than as the source of the code. The difference in approach is that the notebooks give you the reporting vocabulary and the shape of a complete analysis, which books tend to treat more abstractly, while the books and the current PyMC documentation give you code that matches the version you will run. The recipes are most valuable for that reporting step, which is exactly the part the README singles out as the fifth thing in every notebook.

## Conclusion

Adopt this collection if your team is moving from frequentist group comparison to Bayesian methods and wants worked examples that show the whole loop from data shape to posterior summary, because each notebook covers a single model and the Makefile shows how the same code becomes published documentation. Do not adopt it as a dependency, since it is a set of notebooks with no importable package, and note that the PyMC3 code predates the current PyMC release, so the API in the notebooks will not match a modern PyMC installation. Verify first that the model code runs against the PyMC version you use, since the README names PyMC3 and the environment file pins the stack rather than tracking upstream releases, that the examples you need are covered rather than merely adjacent to your problem, since the collection is organised one notebook per model rather than around questions, and that the documentation build still executes the notebooks, because that is the only thing that catches a broken model.

## FAQ

### What is bayesian-analysis-recipes and what is in each notebook?

It is a collection of PyMC3 notebooks with one notebook per model. Each one contains the kind of problem being tackled, a description of how the data should be structured, an example data table that will generally be tidy data, the PyMC3 model code, sometimes two versions of the same model, and examples of how to report findings from the MCMC-sampled posterior.

### Why does the collection argue that Bayesian methods can replace ANOVA?

The README argues that ANOVA only tests whether means of multiple treatment groups are the same, while John Kruschke's BEST, Bayesian Estimation Supersedes the T-Test, gives the estimated posterior distribution over each treatment group, so you can state how any particular pair of groups differ without extra steps such as multiple hypothesis corrections.

### How do I build the documentation for bayesian-analysis-recipes?

The Makefile converts individual notebooks with jupyter nbconvert into a docs directory, and the docs target runs mkdocs serve for the full site. The conversion parameters include --execute with an ExecutePreprocessor.timeout of 600, so notebooks are run as they are converted and the build fails if a model stops working.

### What software does the documentation build need?

The requirements file is used only for building static site docs on Dokku and lists mkdocs, mkdocs-minify-plugin, pymdown-extensions, mkdocs-material and mknotebooks. The repository also has an environment.yml for the analysis stack, and the README carries a Binder badge for running the notebooks in a hosted environment.

### Can I run the bayesian-analysis-recipes notebooks locally?

Yes. The notebooks are Jupyter notebooks, the repository ships an environment.yml for the Python stack, and the README links a Binder launch for a hosted environment. The model code is written against PyMC3, so check that it runs against the PyMC version you have installed.

### How do I suggest a change to bayesian-analysis-recipes?

Post a GitHub issue with your question, or submit a pull request detailing the change and why you think it is important. The README asks you to keep it simple, with no need for essay-length justifications.

## Sources

- [ericmjl/bayesian-analysis-recipes on GitHub](https://github.com/ericmjl/bayesian-analysis-recipes)
- [Issues](https://github.com/ericmjl/bayesian-analysis-recipes/issues)
- [License: MIT](https://github.com/ericmjl/bayesian-analysis-recipes/blob/master/LICENSE)
- [Project website](https://ericmjl.github.io/bayesian-analysis-recipes)
- [README](https://github.com/ericmjl/bayesian-analysis-recipes/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ericmjl-bayesian-analysis-recipes
