{"id":16586719,"url":"https://github.com/williambdean/conjugate","last_synced_at":"2026-04-09T21:09:45.549Z","repository":{"id":177055254,"uuid":"657573095","full_name":"williambdean/conjugate","owner":"williambdean","description":"Bayesian Conjugate Models in Python","archived":false,"fork":false,"pushed_at":"2025-04-15T00:11:10.000Z","size":12545,"stargazers_count":25,"open_issues_count":22,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-15T01:24:45.343Z","etag":null,"topics":["bayesian-inference","data-science","probability-distribution","python","statistical-analysis","statistics"],"latest_commit_sha":null,"homepage":"https://williambdean.github.io/conjugate/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/williambdean.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-23T11:06:53.000Z","updated_at":"2025-04-15T00:10:51.000Z","dependencies_parsed_at":"2024-01-14T11:40:43.103Z","dependency_job_id":"f7c334a9-1ed2-45b1-9096-fba892af9dea","html_url":"https://github.com/williambdean/conjugate","commit_stats":null,"previous_names":["wd60622/conjugate","williambdean/conjugate"],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williambdean%2Fconjugate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williambdean%2Fconjugate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williambdean%2Fconjugate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williambdean%2Fconjugate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/williambdean","download_url":"https://codeload.github.com/williambdean/conjugate/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250080492,"owners_count":21371516,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bayesian-inference","data-science","probability-distribution","python","statistical-analysis","statistics"],"created_at":"2024-10-11T22:52:21.500Z","updated_at":"2026-04-09T21:09:45.542Z","avatar_url":"https://github.com/williambdean.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Conjugate Models\n\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n[![Tests](https://github.com/williambdean/conjugate/actions/workflows/tests.yml/badge.svg)](https://github.com/williambdean/conjugate/actions/workflows/tests.yml)\n[![PyPI version](https://badge.fury.io/py/conjugate-models.svg)](https://badge.fury.io/py/conjugate-models)\n[![docs](https://github.com/williambdean/conjugate/actions/workflows/docs.yml/badge.svg)](https://williambdean.github.io/conjugate/)\n[![codecov](https://codecov.io/github/williambdean/conjugate/branch/main/graph/badge.svg)](https://app.codecov.io/github/williambdean/conjugate)\n\nBayesian conjugate models in Python\n\n## Overview\n\n`conjugate-models` is a modern Python package for Bayesian conjugate inference that prioritizes a clean, idiomatic API and seamless integration with widely used Python data analysis libraries. It implements the conjugate likelihood-prior pairs cataloged in [Fink's compendium](https://www.johndcook.com/CompendiumOfConjugatePriors.pdf) and [Wikipedia's conjugate prior table](https://en.wikipedia.org/wiki/Conjugate_prior), making rigorous Bayesian updating, exploration, and visualization accessible for practitioners, educators, and researchers.\n\n### Why Conjugate Priors?\n\nA prior distribution is conjugate to a likelihood when the posterior remains in the same distribution family after observing data. Conjugate priors provide closed-form posterior updates and posterior predictive distributions, eliminating the need for numerical integration or MCMC sampling. Because these updates are analytic rather than iterative, **posterior computation is instantaneous regardless of data size**—enabling real-time interactive exploration and rapid model iteration.\n\n### Key Benefits\n\n- ⚡ **Instant Updates:** No MCMC or optimization required—posterior computation is immediate\n- 🔢 **Vectorized Operations:** Batch inference for multi-arm problems without explicit loops\n- 📊 **Built-in Visualization:** Plot priors, posteriors, and predictive distributions\n- 🔗 **SciPy Integration:** Direct access to scipy.stats distributions via `.dist` property\n- 📦 **Data Library Support:** Works seamlessly with numpy, pandas, polars, and general array-like objects\n- 🪶 **Lightweight Dependencies:** Minimal requirements—no heavy ML frameworks or complex toolchains\n\n### Lightweight \u0026 Easy to Install\n\nWith minimal dependencies from the scientific Python stack, `conjugate-models` installs quickly without requiring heavyweight probabilistic programming frameworks, MCMC samplers, or complex compilation toolchains.\n\n## Installation\n\n```bash\npip install conjugate-models\n```\n\n## Features\n\n- [Interactive Distribution Explorer](https://williambdean.github.io/conjugate/explorer) for exploring probability distributions with real-time parameter adjustment *(temporarily unavailable — see [#324](https://github.com/williambdean/conjugate/issues/324))*\n- **[Raw Data Workflow](https://williambdean.github.io/conjugate/examples/raw-data-workflow)** - Complete examples from raw observational data to posterior distributions with helper functions\n- **[Data Input Helper Functions](https://williambdean.github.io/conjugate/helpers)** - Extract sufficient statistics from raw observational data for all supported models\n- [Connection to Scipy Distributions](https://williambdean.github.io/conjugate/examples/scipy-connection) with `dist` attribute\n- [Built in Plotting](https://williambdean.github.io/conjugate/examples/plotting) with `plot_pdf`, `plot_pmf`, and `plot_cdf` methods\n- [Vectorized Operations](https://williambdean.github.io/conjugate/examples/vectorized-inputs) for parameters and data\n- [Indexing Parameters](https://williambdean.github.io/conjugate/examples/indexing) for subsetting and slicing\n- [Generalized Numerical Inputs](https://williambdean.github.io/conjugate/examples/generalized-inputs) for any inputs that act like numbers\n    - Out of box compatibility with `polars`, `pandas`, `numpy`, and more.\n- [Unsupported Distributions](https://williambdean.github.io/conjugate/examples/unsupported-distributions) for sampling from unsupported distributions\n\n## Supported Models\n\nMany likelihoods are supported including\n\n- `Bernoulli` / `Binomial`\n- `Categorical` / `Multinomial`\n- `Poisson`\n- `Normal` (including linear regression)\n- and [many more](https://williambdean.github.io/conjugate/models/)\n\nSee the [Quick Reference](https://williambdean.github.io/conjugate/quick-reference) for a complete table of likelihood → prior/posterior mappings with links to model functions and helper functions.\n\n## Basic Usage\n\n### Pattern 1: Working with Pre-processed Data\n\n1. Define prior distribution from `distributions` module\n1. Pass data and prior into model from `models` modules\n1. Analytics with posterior and posterior predictive distributions\n\n```python\nfrom conjugate.distributions import Beta, BetaBinomial\nfrom conjugate.models import binomial_beta, binomial_beta_predictive\n\n# Observed Data (sufficient statistics)\nx = 4  # successes\nN = 10 # trials\n\n# Analytics\nprior = Beta(1, 1)\nprior_predictive: BetaBinomial = binomial_beta_predictive(n=N, distribution=prior)\n\nposterior: Beta = binomial_beta(n=N, x=x, prior=prior)\nposterior_predictive: BetaBinomial = binomial_beta_predictive(\n    n=N, distribution=posterior\n)\n```\n\n### Pattern 2: Working with Raw Observational Data\n\nFor raw data, use **helper functions** from the `helpers` module to extract sufficient statistics:\n\n```python\nimport numpy as np\nfrom conjugate.distributions import Beta\nfrom conjugate.models import binomial_beta\nfrom conjugate.helpers import bernoulli_beta_inputs\n\n# Raw observational data - individual trial outcomes\nraw_data = [1, 0, 1, 1, 0, 1, 0, 1, 1, 0]  # success/failure per trial\n\n# Extract sufficient statistics automatically\ninputs = bernoulli_beta_inputs(raw_data)\nprint(inputs)  # {'x': 6, 'n': 10} - 6 successes in 10 trials\n\n# Use with conjugate model\nprior = Beta(1, 1)\nposterior = binomial_beta(prior=prior, **inputs)\n```\n\n#### Common Helper Function Patterns\n\n```python\nfrom conjugate.helpers import (\n    poisson_gamma_inputs,      # For count data\n    normal_known_variance_inputs,  # For continuous measurements\n    exponential_gamma_inputs,  # For time-between-events data\n    multinomial_dirichlet_inputs,  # For categorical data\n)\n\n# Count data (e.g., website visits per day)\ncount_data = [5, 3, 8, 2, 6, 4, 7, 1, 9, 3]\ninputs = poisson_gamma_inputs(count_data)\n# Returns: {'x_total': sum(count_data), 'n': len(count_data)}\n\n# Continuous measurements with known variance\nmeasurements = [2.3, 1.9, 2.7, 2.1, 2.5]\ninputs = normal_known_variance_inputs(measurements)\n# Returns: {'x_total': sum(measurements), 'n': len(measurements)}\n# Note: variance must be passed separately to the model function\n\n# Time between events (e.g., customer arrivals)\nwait_times = [3.2, 1.8, 4.1, 2.7, 3.9]\ninputs = exponential_gamma_inputs(wait_times)\n# Returns: {'x_total': sum(wait_times), 'n': len(wait_times)}\n\n# Categorical outcomes (e.g., survey responses A, B, C)\nresponses = ['A', 'B', 'A', 'C', 'B', 'A', 'B']\ninputs = multinomial_dirichlet_inputs(responses)\n# Returns: {'x': [3, 3, 1]} - counts for each category\n```\n\nAll 50+ helper functions follow the same pattern: **raw observations in → sufficient statistics out** → ready for conjugate models.\n\nFrom here, do any analysis you'd like!\n\n```python\n# Figure\nimport matplotlib.pyplot as plt\n\nfig, axes = plt.subplots(ncols=2)\n\nax = axes[0]\nax = posterior.plot_pdf(ax=ax, label=\"posterior\")\nprior.plot_pdf(ax=ax, label=\"prior\")\nax.axvline(x=x / N, color=\"black\", ymax=0.05, label=\"MLE\")\nax.set_title(\"Success Rate\")\nax.legend()\n\nax = axes[1]\nposterior_predictive.plot_pmf(ax=ax, label=\"posterior predictive\")\nprior_predictive.plot_pmf(ax=ax, label=\"prior predictive\")\nax.axvline(x=x, color=\"black\", ymax=0.05, label=\"Sample\")\nax.set_title(\"Number of Successes\")\nax.legend()\nplt.show()\n```\n\n\u003cimg height=400 src=\"docs/images/binomial-beta.png\" title=\"Binomial Beta Comparison\"\u003e\n\nMore examples on in the [documentation](https://williambdean.github.io/conjugate/).\n\n## Contributing\n\nIf you are interested in contributing, check out the [contributing guidelines](https://github.com/williambdean/conjugate/blob/main/CONTRIBUTING.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwilliambdean%2Fconjugate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwilliambdean%2Fconjugate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwilliambdean%2Fconjugate/lists"}