You can also find this library at CRAN and download it directly from R and RStudio.
LISTEN TO THIS POST AS A PODCAST:
An introduction to the R package that brings together bivariate hurdle regression, horseshoe regularization, and multi-method causal inference under one roof.
The Problem Nobody Teaches You in Grad School
You have two count variables measured over time. Maybe they are insurgent attacks and counterinsurgent operations in a conflict zone. Maybe they are weekly disease case counts and mortality figures. Maybe they are criminal incidents and arrests in a city.
You know the standard toolkit: Poisson regression, negative binomial if there is overdispersion, maybe a zero-inflated model if zeros pile up. But then the real world intervenes:
- Both series have far too many zeros. Not the kind of “a few extra zeros” that zero-inflated models handle — the kind where 60–80% of observations are zero, and the rest are counts. This is the hallmark of hurdle data: a process that first decides whether anything happens at all, and then, if it does, decides how much.
- The two series influence each other over time. Do counterinsurgent operations today predict insurgent attacks next month? Does disease incidence Granger-cause mortality with a lag? You need cross-lagged dynamics, not two separate regressions.
- You have many potential predictors — economic indicators, population density, climate variables, regime dummies — and your sample size is modest. Overfitting is a real danger.
- You want causal claims, not just correlations, and a single method is not enough. You need converging evidence.
If this sounds familiar, the R package bivarhr was built for exactly your situation.
What bivarhr Does
bivarhr is an open-source R package (MIT-licensed, available on GitHub) that provides a unified workflow for:
- Bivariate hurdle negative binomial regression — jointly modeling two zero-heavy count series with separate zero-generating and count-generating processes.
- Horseshoe priors — automatic Bayesian regularization that shrinks irrelevant coefficients toward zero while letting strong signals survive.
- Bayesian Model Averaging (BMA) via stacking — combining predictions across many candidate models (different lag orders, different regularization strengths) instead of betting everything on one.
- Multi-method causal inference — transfer entropy, Dynamic Bayesian Networks, Hidden Markov Models, VARX models, synthetic control, and sensitivity analysis.
- Rigorous validation — temporal placebo tests, rolling out-of-sample evaluation, extreme bounds analysis, and counterfactual average treatment effects.
All of this runs on top of Stan via the cmdstanr interface, which means full Hamiltonian Monte Carlo sampling with the No-U-Turn Sampler (NUTS) — the gold standard for Bayesian computation.
The Core Model: Bivariate Hurdle Negative Binomial
Let us unpack what the model actually does, without unnecessary jargon.
The Hurdle Idea
A hurdle model splits the data-generating process into two questions:
- Did anything happen? (Zero vs. non-zero.) This is modeled with a Bernoulli distribution and a logit link — essentially a logistic regression.
- If something happened, how much? (Positive counts only.) This is modeled with a truncated negative binomial distribution and a log link.
Mathematically, for each time point and series :
where is the probability of crossing the hurdle (a non-zero count), is the conditional mean of the negative binomial, and is the dispersion parameter.
The key distinction from zero-inflated models: a hurdle model does not distinguish between “structural zeros” and “sampling zeros.” It simply asks whether the count is zero or not, and if not, how large. This is conceptually cleaner and often more appropriate for event count data.
Bivariate Means Cross-Lags
The “bivariate” part means that the model is estimated jointly for two series, and . What makes this powerful is that the design matrices for can include lagged values of , and vice versa. Four specifications are available:
| Specification | C → I | I → C | Interpretation |
|---|---|---|---|
| A | Yes | No | Granger-causes |
| B | No | Yes | Granger-causes |
| C | Yes | Yes | Bidirectional causality |
| D | No | No | No cross-series effects |
By comparing the predictive performance of these specifications, you can formally test whether one series has leading information about the other — a Granger-causality test conducted within a fully Bayesian framework.
Horseshoe Priors: Letting the Data Decide
When you have many candidate predictors and a modest sample size, ordinary maximum likelihood will happily overfit. The horseshoe prior solves this elegantly.
Each coefficient gets a prior that is a mixture of a tight “spike” near zero and a broad “slab” away from zero. The balance between spike and slab is governed by:
- A global shrinkage parameter that controls overall sparsity — how many coefficients the model expects to be non-zero.
- A local shrinkage parameter for each coefficient — allowing individual signals to escape shrinkage if the data support it.
The regularized version used by bivarhr (following Piironen & Vehtari, 2017) adds a slab regularization term that prevents the unbounded coefficient estimates that can afflict the original horseshoe. The result: noise is suppressed, genuine signals are preserved, and you do not need to manually select variables.
In practice, you set a prior guess for the fraction of coefficients you expect to be non-zero (e.g., 0.1 for strong sparsity, 0.5 for moderate). The model does the rest.
Bayesian Model Averaging: Stop Picking One Model
One of the most consequential analytical choices is the lag order: how many past time steps of should enter the equation for ? Different lag orders can tell different stories.
Rather than picking one, bivarhr uses stacking (Yao et al., 2018) to combine predictions across many models. The algorithm finds optimal weights such that the combined predictive distribution:
maximizes the expected log predictive density (ELPD), estimated via Pareto-smoothed importance sampling leave-one-out cross-validation (PSIS-LOO).
This means the final inference is not tied to a single model. Models with good out-of-sample predictive performance get high weight; poor models are down-weighted automatically. The stacking weights themselves are informative: if specification A () consistently gets higher weight than specification D (no cross-lags), that is evidence of a genuine cross-series effect.
The Causal Inference Toolkit
A bivariate regression with cross-lags is a necessary but not sufficient condition for causal claims. bivarhr therefore provides six complementary causal inference methods:
Transfer Entropy
Transfer entropy measures how much knowing the past of series reduces your uncertainty about the current value of series , beyond what ‘s own past already tells you. It is an information-theoretic generalization of Granger causality that makes no linearity assumptions.
bivarhr computes transfer entropy for three data transformations — raw counts, rates (counts per unit exposure), and binary presence/absence — each pre-whitened via an appropriate GLM to remove confounding trends. Permutation-based significance tests (with Benjamini-Hochberg correction) control the false discovery rate.
Dynamic Bayesian Networks (DBN)
A DBN learns a directed acyclic graph over discretized versions of , , and any regime variable, with edges restricted to flow from to . The learned structure reveals which variables are direct parents of which — does yesterday’s regime predict today’s attacks, or only through yesterday’s operations?
Hidden Markov Models (HMM)
An HMM with multivariate Poisson emissions assumes that both and are driven by a latent (hidden) state that evolves over time. The inferred state sequence can reveal regimes — a “calm” state with low counts for both series, an “escalation” state with high counts, and so on — without you having to define them in advance.
VARX Models
A Vector Autoregression with Exogenous variables provides a classical time-series check. bivarhr fits bivariate VAR models and reports stability, serial correlation, normality, and ARCH diagnostics — a complementary perspective to the Bayesian hurdle model.
Sensitivity Analysis
Using the framework of Cinelli and Hazlett (2020), bivarhr quantifies how robust an OLS regression result is to an unobserved confounder. The output is a “robustness value”: how strong would an omitted confounder need to be (in terms of partial ) to explain away the estimated effect? This gives a concrete, interpretable measure of fragility.
Synthetic Control
A Bayesian Structural Time Series (BSTS) model constructs a synthetic counterfactual: what would series have looked like in the absence of a treatment (e.g., a policy intervention, a conflict escalation)? The difference between observed and counterfactual is the estimated causal effect, with full posterior uncertainty intervals.
Validation: Proving Your Results Are Not Artifacts
Temporal Placebo Test
Shuffle the time indices of your data, refit the model, and compare the ELPD to the original. If the original model’s ELPD is substantially higher, the temporal structure is genuine — not an artifact of overfitting.
Rolling Out-of-Sample Evaluation
Split the data at multiple cut points (60%, 70%, 80%, 90% of the sample), fit the model on the training portion, and forecast the remaining observations. The RMSE of these forecasts gives an honest assessment of predictive accuracy.
Extreme Bounds Analysis (EBA)
Re-fit the model with every combination of control variables and check whether the key coefficients (e.g., cross-lag effects) remain stable. If a coefficient flips sign or loses significance when you add or remove a single control, it is fragile.
G-Computation for Average Treatment Effects
Counterfactual ATEs answer the question: “What would happen to if we set the cross-lags and transition variables to zero?” This is the causal estimand that many applied researchers actually care about, computed via posterior predictive simulation.
Getting Started
Installation
# Install the package from GitHubdevtools::install_github("isadorenabi/bivarhr")# Install cmdstanr (required for model fitting)install.packages("cmdstanr", repos = c("https://stan-dev.r-universe.dev", getOption("repos")))cmdstanr::install_cmdstan()# Optional: install packages for full causal inference functionalityinstall.packages(c("RTransferEntropy", "bnlearn", "sensemakr", "CausalImpact", "vars", "openxlsx"))
Minimal Example
library(bivarhr)library(data.table)# Simulate datan <- 100DT <- data.table( I = rpois(n, 5), C = rpois(n, 3), zI = as.integer(rpois(n, 5) > 0), zC = as.integer(rpois(n, 3) > 0), t_norm = seq(-1, 1, length.out = n), t_poly2 = seq(-1, 1, length.out = n)^2, Regime = factor(sample(c("A", "B"), n, TRUE)), trans_PS = sample(0:1, n, TRUE), trans_SF = sample(0:1, n, TRUE), trans_FC = sample(0:1, n, TRUE), log_exposure50 = rep(0, n))# Fit a single model with bidirectional cross-lags and 2 lagsfit <- fit_one(DT, k = 2, spec = "C", iter_warmup = 500, iter_sampling = 500, chains = 2)# Inspectprint(fit$fit$summary())
Bayesian Model Averaging Across Lags and Hyperparameters
# Define a grid of horseshoe hyperparametershs_grid <- expand.grid( hs_tau0 = c(0.1, 0.5, 1.0), hs_slab_scale = c(1, 5), hs_slab_df = 4)# Run BMA over lag orders 0 through 3bma_results <- select_by_bma( DT = DT, spec = "C", k_grid = 0:3, hs_grid = hs_grid, iter_warmup = 1000, iter_sampling = 1200, chains = 4, use_parallel = TRUE)# View model ranking by ELPDprint(bma_results$table)
Transfer Entropy
te_results <- run_transfer_entropy(DT, lags = 1:3, shuffles = 200, seed = 123)print(te_results)
Where This Matters
The applications extend well beyond conflict analysis. Any domain with paired zero-heavy count time series is a candidate:
- Public health: Disease incidence and mortality; hospital admissions and readmissions; vaccination rates and outbreak counts.
- Criminal justice: Criminal incidents and law enforcement responses; drug seizures and overdose deaths.
- Economics: Firm entry and exit counts; patent applications and citations; trade flow counts between countries.
- Ecology: Predator and prey counts; species occurrence and extinction events; colonization and local disappearance.
- Social science: Protest events and government responses; legislative proposals and vetoes; online misinformation posts and fact-checking activity.
Under the Hood: Technical Details
For those who want to look inside:
| Component | Implementation |
|---|---|
| Sampler | Stan NUTS (No-U-Turn Sampler) via cmdstanr |
| Shrinkage | Regularized horseshoe (Piironen & Vehtari, 2017) |
| Model comparison | with stacking weights (Yao et al., 2018) |
| Convergence | , , zero divergences |
| LOO reliability | Pareto for all observations |
| Dispersion | Truncated log-normal prior on |
The Stan model code is fully transparent — you can inspect it via get_hurdle_model() — and the generated quantities block produces posterior predictive checks, pointwise log-likelihoods, and fitted values out of the box.
Diagnostic Checklist
Before trusting your results, bivarhr encourages you to verify:
| Metric | Target | Warning sign |
|---|---|---|
| < 1.01 | > 1.05 means chains did not converge | |
| (bulk) | > 400 | < 400 means inefficient sampling |
| Divergences | 0 | Any divergence suggests geometric pathologies |
| Pareto | < 0.7 | > 0.7 means LOO approximation is unreliable |
| difference | > 5 for “strong” preference | < 2 means models are practically equivalent |
The Bigger Picture
What makes bivarhr distinctive is not any single component — hurdle models exist, horseshoe priors exist, transfer entropy exists — but the integration. The package recognizes that in applied work, the bottleneck is not any one method’s sophistication. It is the workflow: getting from raw data to a validated causal claim, with uncertainty quantification, in a reproducible pipeline.
By combining a carefully specified bivariate hurdle model with automatic regularization, principled model averaging, and six complementary causal inference methods — all validated through placebo tests and out-of-sample evaluation — bivarhr gives applied researchers a framework that is both rigorous and practical.
If your work involves paired count time series with excess zeros and you care about causal inference, this package deserves a serious look.
bivarhr is open-source (MIT License) and available at github.com/isadorenabi/bivarhr.
Author: José Mauricio Gómez Julián. ORCID.
Citation:
@software{gomez2025bivarhr, author = {Gómez Julián, José Mauricio}, title = {bivarhr: Bivariate Hurdle Regression with Bayesian Model Averaging}, year = {2025}, url = {https://github.com/isadorenabi/bivarhr}}
Built on Stan, cmdstanr, and the broader Bayesian ecosystem. The author thanks the Stan development team for their foundational work.


Leave a Comment/Deja un Comentario