Atlas
statminds
Dual-Process GLM (Two-Part Modeling)The underlying model family class (e.g. GLM, linear model, categorical matrix, log-linear).Parametric ReferenceStatistical methods that assume a specific probability distribution family (typically normal).12-stage workflow

Zero-Inflated & Hurdle Models

The engine for Multi-Part Count Discovery. These models audit datasets with an 'Excess of Zeros' by splitting the story into two parts: the choice to participate (0 vs. >0) and the frequency of participation.

Model familyDual-Process GLM (Two-Part Modeling)
Hypothesistwo-part test
AliasesZIP (Zero-Inflated Poisson) · ZINB (Zero-Inflated Negative Binomial) · Hurdle Modeling · Two-Part Count Models
G1
Zero-Neutralization
Identify if 'Excess Zeros' come from a different logical process than the count itself (e.g., Never-Users vs. Occasional-Users).
G2
Dual-Factor Audit
Simultaneously model the probability of an event occurring AND the frequency of its recurrence.
G3
Structural Precision
Differentiate between a 'Hurdle' (all zeros are from one process) and 'Zero-Inflation' (zeros can come from two sources).
1

What is it?

Zero-Inflated & Hurdle Models model count datasets containing an excess frequency of zero counts (more zeros than predicted by standard Poisson or Negative Binomial distributions).

2

When to use it

  • Excess Zeros: Histograms exhibit a massive zero spike.
  • Dual Pathways: Two processes exist—structural zeros vs count generation.
  • Hurdle vs Zero-Inflated: Hurdle models force all zeros through one binary barrier.
3

Excess Zeros Spike

Notice the massive count frequency peak at exactly 0. Standard distributions cannot fit this inflation, necessitating a dual-stage model:

Zero SpikeCounts
Interactive Sandbox

Zero-Inflated Count Live Laboratory

Adjust the zero-inflation probability rate to watch the zero peak rise relative to count densities.

Presets
Zero-Inflation Probability40%
Poisson Lambda Rate3.0
Count Frequency Histogram (X axis counts: 0 to 8; Y axis frequency)Zero spike highlighted in red
0181425334254617182
The 12-Stage Precision Workflow
01The Zero Split
Hypotheses
We test two nulls: that zero influence exists in the probability of 'Not Participating' and zero influence in the 'Frequency' of those who do.
02Process Independence
Assumptions
Ensuring the 'Zero Process' and the 'Count Process' can be meaningfully separated without mathematical collision.
03Vuong Forensics
Diagnostics
Utilizing the Vuong Test to compare standard Poisson/NB against Zero-Inflated versions—the ultimate proof of model necessity.
04focus
Predicting the Number of ER Visits—where most people have 0, some have 0 because they are healthy, and some have 0 by chance.
05Hurdle Pivot
Alternatives
Knowing when to switch to a Hurdle Model if the 0 value represents an absolute barrier that must be crossed (e.g., buying a product).
06Likelihood Strike
Significance
Executing significance tests for both the Logit part (Probability) and the Poisson part (Rate)—a dual-strike audit.
07The Dual IRR
Effect Size
Interpreting Odds Ratios for the 'Zero' part and Incidence Rate Ratios for the 'Count' part simultaneously.
08Zero Density
Sample Size
Calculating the N required to provide stable estimates for both equations—ensuring the 'Non-Zero' group is large enough to model.
09The Two-Table Story
Reporting
Reporting two sets of coefficients: one for the 'Zero Inflation' process and one for the 'Count' process.
10pscl Logic
Software
Executing the 'zeroinfl' or 'hurdle' commands, ensuring the model formula correctly specifies the inflation predictors (after the | pipe).
11focus
Avoiding the error of ignoring the zero-process—running a standard Poisson on zero-heavy data leads to dangerously biased p-values.
12focus
Tracing the model back to Lambert (1992) and the foundational shift from single-process to dual-process count forensics.
01Hypothesis test logic

Hypotheses

Pragmatic null and alternative hypotheses defined in mathematical notation.

We ask not just 'is there a link?', but 'how much does Y change for every unit of X?'
Logic Core
Null · H₀

H₀: No effect in zero-inflation process (logit part) AND no effect in count process (log link part)

Alternative · Hₐ

Hₐ: Effect exists in zero-inflation process OR count process (or both)

Why it matters two-part test

Zero-inflated models have TWO parts: (1) Binary process modeling excess zeros (logit: π = P(structural zero)), and (2) Count process modeling non-zero counts (log-linear: λ = E[Y|Y>0]). Hurdle models differ: zeros come from one process, positives from truncated count distribution. Test each part separately with Wald or LR tests.

02Model diagnostics

Assumptions

The core mathematical criteria needed to ensure that statistical testing remains unbiased and valid.

Linearity is a strong claim. Nature often curves; ensure your model does not force a straight line on a bent world.
Integrity Shield
7
Assumptions
4
Critical / High Severity
How to check
Quick
Compare observed proportion of zeros to Poisson/NB expected: P(Y=0) = exp(-λ) for Poisson. If observed >> expected, excess zeros present. Rule of thumb: if >60-70% zeros, likely zero-inflated.
Rigorous
Vuong test comparing ZIP vs Poisson (or ZINB vs NB): positive statistic favors zero-inflated model, negative favors standard model, p < .05 indicates significant preference. Score test for zero-inflation. AIC/BIC comparison.
If violated
If no excess zeros (Vuong test favors standard model): (1) Use standard Poisson or negative binomial regression. (2) Check for overdispersion: if variance > mean, use NB instead of Poisson. If underdispersion (rare), use generalized Poisson. If zero-inflation not supported by data, simpler models preferable (parsimony).
poisson regression
How to check
Quick
Theoretical justification: do zeros represent two types (e.g., non-drinkers vs drinkers who didn't drink during study period)? Subject-matter knowledge about zero-generating mechanisms. Check if predictors differ between zero and count parts.
Rigorous
Compare coefficients between zero and count parts (if similar, may not need separate processes). Test if same covariates predict zeros and counts differently. Examine residuals for two-component mixture patterns.
If violated
If zeros come from single process: (1) Use hurdle model instead of zero-inflated (hurdle assumes all zeros from one source, counts from truncated distribution). (2) Use standard count regression if no excess zeros. (3) If uncertainty about mechanism, fit both ZIP and hurdle, compare fit and interpret substantively.
poisson regression
How to check
Quick
Design review: check for repeated measures (same subjects over time), clustering (students in schools, patients in clinics), or spatial dependence. Verify each subject contributes once.
Rigorous
Calculate ICC if clustering suspected. Check for overdispersion beyond NB can handle (may signal unmeasured clustering). Examine residuals for patterns by cluster.
If violated
If repeated measures: (1) Use zero-inflated mixed models (ZIMM, ZINB with random effects) in glmmTMB or brms. (2) GEE for zero-inflated counts with working correlation structure. If clustered: (3) Mixed effects zero-inflated models with random intercepts for clusters. (4) Cluster-robust standard errors if random effects not needed.
gee
How to check
Quick
Calculate mean and variance of non-zero counts. If variance >> mean (ratio > 2-3), overdispersion present. Check dispersion parameter estimate in ZINB model.
Rigorous
Likelihood ratio test comparing ZIP vs ZINB (test if dispersion parameter θ = 0). If θ significantly different from 0, NB better fits overdispersion. Pearson chi-square / df for goodness-of-fit.
If violated
If overdispersion detected: (1) BEST: Use zero-inflated negative binomial (ZINB) instead of ZIP. NB adds dispersion parameter to handle extra-Poisson variance. (2) Check if clustering causing overdispersion → use mixed models. (3) If underdispersion (rare), use zero-inflated generalized Poisson.
How to check
Quick
Correlation matrix: |r| > .80 problematic. Check if adding/removing predictors drastically changes coefficients. VIF can be calculated for each part separately (logit and count).
Rigorous
Variance inflation factors for zero-inflation predictors and count predictors separately. Condition indices. Check stability of estimates across model specifications.
If violated
If VIF > 10: (1) Remove one predictor from highly correlated pair (choose based on theory). (2) Create composite scores. (3) Use regularized regression (lasso, elastic net for zero-inflated models via glmnet with custom family). (4) Center continuous predictors if interactions present.
ridge regression
How to check
Quick
Count number of zeros (for zero part) and non-zeros (for count part). For zero part: need ≥10 zeros per predictor. For count part: need ≥10 non-zero observations per predictor. Total model has 2×k parameters for k predictors (if same predictors in both parts).
Rigorous
Simulation-based power analysis for zero-inflated models. Check convergence and SE estimates (large SEs suggest insufficient data). Bootstrap CIs to assess stability.
If violated
If sample too small: (1) Reduce number of predictors (select based on theory, prior research). (2) Use penalized likelihood (Firth correction). (3) Combine categories if categorical predictors have sparse cells. (4) Consider simpler model (e.g., Poisson instead of ZIP if justified). (5) Increase sample size if feasible.
How to check
Quick
Logit link for binary zero/non-zero process is standard. Log link for count part ensures positive predictions. Check if predicted probabilities and counts are in valid ranges (0-1 for probabilities, >0 for counts).
Rigorous
Compare alternative links (probit for zero part, identity or sqrt for count part) via AIC/BIC. Box-Cox transformation can suggest optimal link. Check linearity of predictors on logit/log scale.
If violated
If logit link inadequate for zero part: (1) Try probit or complementary log-log link (rarely needed). If log link inadequate for count part: (2) Try identity link (but risks negative predictions) or sqrt link. (3) Transform predictors instead of changing link. (4) In practice, logit and log links almost always appropriate for ZIP/ZINB.
03Residual Forensics

Diagnostics

Checking residual plots and indices to examine model deviations and ensure standard error integrity.

Trust, but verify. The outliers often hold more truth than the averages.
System Health
Essential checks
  1. Vuong test (ZIP vs Poisson, or ZINB vs NB): tests zero-inflation necessity
  2. Check proportion of zeros (observed vs expected under Poisson/NB)
  3. Test overdispersion (variance vs mean for non-zero counts)
  4. Likelihood ratio test (ZIP vs ZINB: test if dispersion parameter needed)
  5. Model convergence check
Recommended checks
  1. Rootograms (hanging rootogram) for visualizing zero-inflation fit
  2. Residual plots (Pearson, deviance) to check for patterns
  3. Predicted vs observed frequency distribution
  4. AIC/BIC comparison across ZIP, ZINB, hurdle models
  5. Score test for zero-inflation
  6. VIF for multicollinearity in each part
  7. Check for influential observations (Cook's D)
  8. Pseudo-R² (McFadden, Nagelkerke) for overall fit
04Live Instances

Applied Minds

Review concrete study examples, data layout guidelines, and copy executable syntax scripts.

Theory is the map. Practice is the terrain. Simulation bridges the gap.
Applied Wisdom
Example 01

Yoga Practice and Doctor Visits (Zero-Inflated Poisson)

Research question: Does regular yoga practice reduce healthcare utilization (doctor visits) in adults? Design: Cross-sectional survey (n=500). Outcome: Number of doctor visits in past year (count with 62% zeros). Predictors: Yoga practice (yes/no), age, chronic conditions. Challenge: Excess zeros (never-users vs didn't need care vs needed but didn't go).

DesignCross-sectional with excess zeros
Outcome ScaleDoctor visits in past year (count, 0-50)
# Zero-Inflated Poisson Regression: Yoga → Doctor Visits
library(pscl)         # For zeroinfl()
library(MASS)         # For negative binomial
library(ggplot2)
library(countreg)     # For rootograms (install from R-Forge)

set.seed(2025)

# Simulate data with excess zeros
n <- 500
age <- runif(n, 25, 75)
chronic <- rpois(n, lambda=1.2)
yoga <- sample(c(0, 1), n, replace=TRUE, prob=c(0.65, 0.35))

# Zero-inflation process (structural zeros: never-users)
logit_zero <- -1 + 0.8*yoga - 0.02*age + 0.3*chronic
pi_zero <- plogis(logit_zero)  # Probability of structural zero

# Count process (for non-structural zeros)
lambda <- exp(1.5 - 0.4*yoga + 0.01*age + 0.3*chronic)

# Generate outcome
structural_zero <- rbinom(n, 1, pi_zero)
doctor_visits <- ifelse(structural_zero == 1, 0, rpois(n, lambda))

data <- data.frame(visits=doctor_visits, yoga, age, chronic)

cat("=== Data Summary ===\n")
cat("Total observations:", n, "\n")
cat("Zeros:", sum(data$visits == 0), "(", round(mean(data$visits==0)*100, 1), "%)\n")
cat("Mean:", round(mean(data$visits), 2), "\n")
cat("Variance:", round(var(data$visits), 2), "\n")
cat("Variance/Mean ratio:", round(var(data$visits)/mean(data$visits), 2), "\n\n")

# === STEP 1: Check for Excess Zeros ===

# Compare observed zeros to Poisson expected
poisson_fit <- glm(visits ~ yoga + age + chronic, data=data, family=poisson)
poisson_lambda <- mean(predict(poisson_fit, type="response"))
expected_zeros_poisson <- exp(-poisson_lambda)

cat("=== Zero Inflation Check ===\n")
cat("Observed proportion of zeros:", round(mean(data$visits==0), 3), "\n")
cat("Expected under Poisson:", round(expected_zeros_poisson, 3), "\n")
cat("Excess zeros:", ifelse(mean(data$visits==0) > expected_zeros_poisson, "YES", "NO"), "\n\n")

# === STEP 2: Fit Zero-Inflated Poisson (ZIP) ===

zip_model <- zeroinfl(visits ~ yoga + age + chronic | yoga + age + chronic,
                      data=data, dist="poisson")

summary(zip_model)

cat("\n=== Model Interpretation ===\n")
cat("\nCount part(log-linear for E[Y|Y>0]):")
cat("\n- Yoga coefficient:", round(coef(zip_model)["count_yoga"], 3))
cat("\n- IRR(incidence rate ratio):", round(exp(coef(zip_model)["count_yoga"]), 3))
cat("\n- Interpretation: Yoga reduces doctor visits by", 
    round((1-exp(coef(zip_model)["count_yoga"]))*100, 0), "% among those who visit\n")

cat("\nZero part(logit for P(structural zero)):")
cat("\n- Yoga coefficient:", round(coef(zip_model)["zero_yoga"], 3))
cat("\n- OR for zero:", round(exp(coef(zip_model)["zero_yoga"]), 3))
cat("\n- Interpretation: Yoga increases odds of being never-user by", 
    round((exp(coef(zip_model)["zero_yoga"])-1)*100, 0), "%\n\n")

# === STEP 3: Test for Zero-Inflation (Vuong Test) ===

vuong_test <- vuong(poisson_fit, zip_model)
print(vuong_test)

cat("\nVuong test interpretation:")
if(vuong_test$statistic > 1.96) {
  cat("\nZIP model significantly better than Poisson(p < .05)")
  cat("\nZero-inflation supported by data.\n")
} else {
  cat("\nNo significant preference for ZIP over Poisson.")
  cat("\nZero-inflation may not be necessary.\n")
}

# === STEP 4: Check for Overdispersion ===

# Compare ZIP vs ZINB
zinb_model <- zeroinfl(visits ~ yoga + age + chronic | yoga + age + chronic,
                       data=data, dist="negbin")

cat("\n=== Overdispersion Check ===\n")
cat("ZIP AIC:", AIC(zip_model), "\n")
cat("ZINB AIC:", AIC(zinb_model), "\n")
cat("Prefer model with LOWER AIC\n")

if(AIC(zinb_model) < AIC(zip_model) - 2) {
  cat("\nZINB preferred(overdispersion present)\n")
  final_model <- zinb_model
} else {
  cat("\nZIP adequate(no strong overdispersion)\n")
  final_model <- zip_model
}

# === STEP 5: Predicted Probabilities ===

# Predicted counts for yoga vs no yoga (at mean age, mean chronic conditions)
new_data <- data.frame(
  yoga = c(0, 1),
  age = rep(mean(data$age), 2),
  chronic = rep(mean(data$chronic), 2)
)

pred_counts <- predict(final_model, newdata=new_data, type="response")
pred_zero_prob <- predict(final_model, newdata=new_data, type="zero")

cat("\n=== Predictions(at mean age, mean chronic conditions) ===\n")
cat("No Yoga: E[visits] =", round(pred_counts[1], 2), 
    ", P(zero) =", round(pred_zero_prob[1], 3), "\n")
cat("Yoga:    E[visits] =", round(pred_counts[2], 2),
    ", P(zero) =", round(pred_zero_prob[2], 3), "\n")

# === STEP 6: Visualization ===

# Observed vs predicted frequency distribution
obs_freq <- table(data$visits)
pred_freq <- colSums(predict(final_model, type="prob"))

plot_data <- data.frame(
  count = as.numeric(names(obs_freq)),
  observed = as.vector(obs_freq),
  predicted = pred_freq[1:length(obs_freq)]
)

ggplot(plot_data, aes(x=count)) +
  geom_bar(aes(y=observed/sum(observed)), stat="identity", 
           fill="steelblue", alpha=0.6, width=0.4, position=position_nudge(x=-0.2)) +
  geom_bar(aes(y=predicted/sum(predicted)), stat="identity",
           fill="coral", alpha=0.6, width=0.4, position=position_nudge(x=0.2)) +
  labs(title="Observed vs Predicted Frequency: Doctor Visits",
       x="Number of Doctor Visits", y="Proportion") +
  scale_x_continuous(breaks=seq(0, max(plot_data$count), by=2)) +
  theme_classic() +
  annotate("text", x=max(plot_data$count)*0.7, y=max(plot_data$observed/sum(plot_data$observed))*0.9,
           label="Blue = Observed\nRed = Predicted", size=4)

# === APA-Style Reporting ===
cat("\n=== APA-Style Report ===\n")
cat("A zero-inflated Poisson regression examined the association between yoga\n")
cat("practice and healthcare utilization(doctor visits, n=500). The outcome\n")
cat("exhibited substantial zero-inflation(62% zeros vs 35% expected under\n")
cat("Poisson). Vuong test confirmed ZIP model significantly outperformed\n")
cat("standard Poisson(z = X.XX, p < .001). The model included two parts:\n")
cat("\n(1) Zero-inflation(never-users): Yoga practice increased odds of being\n")
cat("a never-user(OR = 2.23, p = .003), suggesting yoga practitioners may\n")
cat("avoid medical care for preventive reasons.\n")
cat("\n(2) Count process(conditional visits): Among those who use healthcare,\n")
cat("yoga reduced visit frequency by 33% (IRR = 0.67, p < .001), indicating\n")
cat("yoga's protective health effects reduce need for medical visits.\n")
cat("\nModel fit was adequate(AIC = XXX, pseudo-R² = .XX). Findings support\n")
cat("yoga's dual role in promoting health(fewer visits when used) and\n")
cat("possibly encouraging preventive self-care(more never-users).\n")
Interpretation Blueprint

ZIP model revealed dual effects of yoga on healthcare utilization. Zero-inflation part (logit): Yoga increased odds of being a structural zero (never-user) by 123% (OR=2.23, p=.003), suggesting yoga practitioners may engage in more self-care and preventive health behaviors, reducing need for medical visits. Count part (log-linear): Among those who do use healthcare, yoga reduced visit frequency by 33% (IRR=0.67, p<.001), indicating yoga's health-protective effects. Vuong test confirmed ZIP significantly outperformed standard Poisson (z=4.52, p<.001), validating zero-inflation. With 62% zeros (vs 35% expected under Poisson), two-part model necessary. Results align with research showing yoga reduces healthcare costs and utilization through improved health and self-management.

05Tactical Pivots

Alternatives

Structured fallback pathways for choosing alternative tests when normality or slopes requirements fail.

When the path is blocked, pivot. Rigor is not rigidity; it is the intelligent adaptation to reality.
Adaptive Strategy
Measurement Precision Ladder Ideal · Zero-Heavy Counts
Ratio
Consider Tobit or Heckman Selection models if the outcome is continuous but zero-heavy.
Model Collapse
Count
Maintain Zero-Inflated/Hurdle logic. Ideal for modeling 'Participation' vs 'Intensity' as two distinct stories.
Peak Signal
Balanced Count
Simplify to standard Poisson or Negative Binomial if the number of zeros matches distributional expectations.
Over-Complexity
Binary
Abandon Two-Part logic. Use Logistic Regression if you only care about 'Occurrence' and not 'Frequency'.
Identity Loss
Temporal Trajectory Audit Static Multi-Part Snapshot
Static Zero-Split
Single point audit.
Stay with ZIP/ZINB. Decipher the drivers of 'Always Zero' vs 'Occasional Success'.
Repeated Multi-Part
Trajectory Process-flips.
Pivot to Multilevel Zero-Inflated Poisson (GLMM) to account for longitudinal subject clustering.
Adaptive Technical Safeguards · adaptive safeguards
model specification error
  • Vuong Test Strike — Mandatory audit to prove the Zero-Inflated model is superior to the standard GLM.
  • Hurdle vs ZIP Pivot — Choose ZIP if zeros can come from both processes; choose Hurdle if all zeros are from the 'Boundary' process.
overdispersion in count part
  • Zero-Inflated Negative Binomial (ZINB) — The mandatory shift if the non-zero counts are themselves overdispersed.
  • Robust Multi-Part GLM — Apply M-estimators to the frequency portion of the model.
non convergence
  • Bayesian Two-Part Model — Use informative priors to stabilize the complex joint likelihood estimation.
06Adjusted Comparisons

Post-hoc

Group mean comparisons and correction controls (e.g. Tukey HSD, Bonferroni) to protect against Family-Wise Error Rates.

The omnibus test opens the door; post-hoc analysis explores the room.
Forensic Detail
Adjusted Comparisons

Post-hoc pairwise tests defined for this model.

Interpretation Guidelines

No specific guidelines provided.

07Standardized scale impact

Effect Size

Understanding effect sizes (e.g., Cohen's d, Partial Eta-Squared) and clinical impact benchmarks.

Significance is noise. Magnitude is the signal. Measure the impact, not just the probability.
Impact Magnitude

IRR from count part. IRR=1.5 means 50% increase in expected count. IRR=0.7 means 30% decrease. IRR=1.0 means no effect. Report with 95% CI.

OR from zero-inflation part. OR=2.0 means doubling odds of structural zero. OR=0.5 means halving odds. Interpret as logistic regression.

McFadden, Nagelkerke, or Cox-Snell R² for overall model fit. Values 0.2-0.4 considered good for count models. Not directly comparable to OLS R².

Recommended Metric: IRR for count part (primary), OR for zero part, pseudo-R² for model-level fit
Small
0.2
Medium
0.5
Large
0.8
0.50
IRR for count part (primary), OR for zero part, pseudo-R² for model-level fit
Recommended Measure
3
Available Metrics
ReportUse IRR for count part (primary), OR for zero part, pseudo-R² for model-level fit to represent clinical impact magnitude.
08Statistical Power

Sample Size

Guidelines for minimum sample requirements and power analysis parameters.

An underpowered study is an ethical failure. Respect the data by collecting enough of it.
Power Protocol
Floor Requirements

The 'Process Separation' Minimum: A minimum of 100 participants is essential. Two-part models must estimate two separate equations simultaneously—one for 'Being Zero' and one for the 'Count Value'.

Effect SizeParametersRequired n
Small EffectLow Signal (OR=1.5, IRR=1.2)n ≈ 1000
Medium EffectModerate Signal (OR=2.5, IRR=1.5)n ≈ 250
Large EffectStrong Signal (OR=4.0, IRR=2.0)n ≈ 100
Key considerations

The 'Zero Density' Strike: If your sample has 95% zeros, the 'Count' part will have zero power. If it has 5% zeros, the 'Zero Inflation' part will collapse. Strive for a 'Zero Ratio' between 20% and 80% for maximum stability.

G*Power StrategyBenchmark: Z-tests → Zero-Inflated Poisson (ZIP). Parameters: Odds Ratio (Zero part), IRR (Count part), α = .05, Power = .80. Note: Power is maximized when both the 'Zero' and 'Count' processes have high-fidelity signals.
09APA narrative blueprint

Reporting

How to compile statistical results into publication prose matching APA and journal style guides.

The Beta coefficient is the currency of change. Interpret it in real-world units, not just standardized abstractions.
Narrative Arc
Worked APA paragraph example
A zero-inflated Poisson regression examined the association between yoga practice and healthcare utilization (doctor visits, n=500, 62% zeros vs 35% expected under Poisson). Vuong test confirmed ZIP significantly outperformed standard Poisson (z=4.52, p<.001), supporting zero-inflation. The model revealed two distinct effects: (1) Zero-inflation part: Yoga increased odds of being a never-user of healthcare by 123% (OR=2.23, 95% CI [1.34, 3.71], p=.003), suggesting enhanced preventive self-care. (2) Count part: Among healthcare users, yoga reduced visit frequency by 33% (IRR=0.67, 95% CI [0.54, 0.83], p<.001), indicating health-protective effects. Model fit was adequate (AIC=1423, pseudo-R²=.18). Findings support yoga's dual benefits: promoting health independence and reducing medical need among users.
Reusable template

A zero-inflated Poisson / zero-inflated negative binomial / hurdle regression examined research question. The outcome was count variable (n=sample size, X% zeros). If tested: Vuong test confirmed model outperformed comparison model (z=value, p=value). If ZINB: Overdispersion was present (dispersion parameter θ=value, variance/mean=ratio). The model included two parts: (1) Zero-inflation/hurdle part (logit): Predictor increased/decreased odds of structural zero / any event (OR=value, 95% CI X, X, p=value). (2) Count part (log-linear): Among non-zero/positive cases, predictor was associated with X% increase/decrease in outcome (IRR=value, 95% CI X, X, p=value). Model fit was adequate/good (AIC=value, pseudo-R²=value). Conclude with interpretation.

Essential statistics to report
  • Sample size and proportion of zeros
  • Model type (ZIP, ZINB, hurdle) and justification
  • Vuong test or AIC/BIC comparison if models compared
  • Dispersion parameter (if ZINB)
  • Odds ratios with 95% CI for zero part
  • Incidence rate ratios with 95% CI for count part
  • p-values for each coefficient
  • Model fit statistics (AIC, pseudo-R²)
10Exhibit Builder

Manuscript Lab

Copy standard summary tables and forensic reporting grids to outline analysis details.

Table 1: Zero-Inflated Poisson (ZIP) for Excess Zeros
Model PartPredictorBSEzpOR / IRR
Binary (Zero-Inflation)Self-Care Knowledge-1.450.45-3.22.0010.23 (OR)
Binary (Zero-Inflation)Health Insurance1.120.382.95.0033.06 (OR)
Count (Poisson)Severity Score0.420.104.20< .0011.52 (IRR)
Count (Poisson)Age0.080.042.00.0451.08 (IRR)
Note. Outcome: Number of ER visits. N = 400. Vuong test confirms ZIP > Poisson (p < .01).
Knowledge (OR = 0.23)Identifies the Zero-Driver. High self-care knowledge reduces the odds of being a 'False Zero' (someone who never goes) by 77%, making them a 'Strategic Zero' (intentional avoidance).
Severity (IRR = 1.52)For those who do go to the ER, each point of severity increases the frequency of visits by 52%.
Header glossary

The 'Always Zero' Predictor. Estimates the probability that a person is a 'True Zero' (e.g., someone who NEVER visits the ER, regardless of severity).

The 'Frequency' Predictor. Estimates the number of visits for those who DO visit (the non-zero population).

11Algorithmic Logic

Command Center

Syntax libraries and function parameters for executing calculations in stats packages.

Code your model to handle residuals. The errors tell you what your model missed.
Execution Engine
# 1. Fit Zero-Inflated Poisson (ZIP)
model <- pscl::zeroinfl(visits ~ severity | knowledge, data = df)

# 2. Modern Alternate (glmmTMB)
model_tmb <- glmmTMB::glmmTMB(visits ~ severity + (1|id), ziformula = ~ knowledge, data = df, family = poisson)
Library stack
R
psclglmmTMB
Python
statsmodels
Elite Forensic Strike

Zero-inflation is not just 'too many zeros'. It's about 'Two types of Zeros' (structural vs random). If your zeros are all the same type, use a Hurdle model instead.

# Vuong Test (Poisson vs ZIP)
pscl::vuong(poisson_mod, zip_mod)

# Rootogram for Zero-Fit
countreg::rootogram(zip_mod)
12The Over-adjustment Trap

Common Mistakes

Analytical caveats and corrections to maintain modeling integrity.

Wisdom is learning from the failures of others. Anticipate the error before it occurs.
Defensive Logic
Why it's wrong
If observed zeros match Poisson/NB expectation, zero-inflated models add unnecessary complexity without improving fit. Vuong test would not favor ZIP over standard model. Overfitting and unstable estimates result from fitting more complex model than data support.
The correction
Always check proportion of zeros vs expected. Run Vuong test comparing ZIP vs Poisson (or ZINB vs NB). If p>.05 or test favors simpler model, use standard Poisson/NB. Parsimony principle: prefer simpler model unless data clearly require complexity.
Why it's wrong
ZIP assumes Poisson distribution for count part (variance=mean). With overdispersion, ZIP underfits, leading to poor predictions, biased SEs, and inflated Type I errors. Residuals show systematic patterns.
The correction
Calculate variance/mean ratio for non-zero counts. If ratio >2-3, use ZINB instead of ZIP. Test via likelihood ratio comparing ZIP vs ZINB. If ZINB dispersion parameter θ significantly different from infinity (or 0 depending on parameterization), overdispersion confirmed.
Why it's wrong
Zero part coefficients are on logit scale (odds of structural zero); count part on log scale (log of expected count). Positive coefficient in zero part INCREASES odds of zero (DECREASES expected count overall). Signs can be opposite in two parts, and this is substantively meaningful.
The correction
Report each part separately with clear labels. Zero part: exponentiate for OR of structural zero. Count part: exponentiate for IRR of counts given non-zero. Interpret in context: 'Yoga increases odds of being never-user (zero part, OR=2.2) but reduces visit frequency among users (count part, IRR=0.7).'
Why it's wrong
Hurdle: zeros from single process, positives from truncated count distribution. ZIP: zeros from mixture (structural + sampling zeros). Using wrong model misrepresents data-generating process. Interpretation differs: hurdle is two-stage (any vs how many), ZIP is mixture.
The correction
Choose based on theory about zeros. If zeros = absence of behavior/event (e.g., no injuries, no purchases), use hurdle. If zeros include both never-users and unlucky users (e.g., non-drinkers vs drinkers who didn't drink today), use ZIP. Compare both via AIC/BIC and interpret results in light of theory.
Why it's wrong
Non-convergence or huge SEs indicate model estimation problems: separation, multicollinearity, insufficient data, model misspecification. Results are unreliable even if model 'runs'. P-values and CIs invalid.
The correction
If convergence fails: (1) Check for perfect predictors (all one group has zero), (2) Reduce predictors, (3) Scale continuous variables, (4) Check for multicollinearity (VIF), (5) Increase sample size or simplify model. If large SEs: check if predictors have sufficient variation and no separation.
Why it's wrong
While convenient, using identical predictors in zero and count parts may not reflect theory. Some predictors may only affect zero-inflation (e.g., demographic 'never-user' status) while others affect count (e.g., intensity of use). Forcing same predictors wastes degrees of freedom and reduces interpretability.
The correction
Use theory to guide predictor selection for each part. Zero part: predictors of 'never-user' status or structural zeros. Count part: predictors of intensity/frequency among users. Test if predictors can be constrained to be equal across parts via likelihood ratio test. Report different predictors if theory supports.
Why it's wrong
ZIP, ZINB, hurdle Poisson, hurdle NB can all fit data, but one may be clearly superior. Without comparison, may use suboptimal model. Residual patterns indicate misfit. Poor fit → biased estimates and incorrect inference.
The correction
Always compare models via AIC/BIC (lower better). Vuong test for nested comparisons. Examine rootograms (hanging rootograms show observed vs fitted frequencies). Check residual plots. Report model selection process and justification for chosen model.
Why it's wrong
Zero and count parts are estimated jointly, not separately. The two parts are linked through the likelihood. Marginal effects combine both parts. Overall expected count E[Y] depends on both parts: E[Y] = (1-π) × λ where π=P(structural zero), λ=E[count|not structural zero].
The correction
Report both parts but also marginal effects on overall expected count. Calculate predicted counts via predict(type='response') which combines both parts. For interpretation: 'Overall, yoga reduced expected visits from 3.2 to 2.1, achieved through both increasing never-users (zero part) and reducing frequency among users (count part).'
13Academic Lineage

References

Scholarly lineage and citation keys grounding the statistical framework.

We stand on the shoulders of giants. Honor the source of the method.
Academic Lineage
[1]
Lambert, D. (1992). Zero-inflated Poisson regression, with an application to defects in manufacturing. Technometrics, 34(1), 1-14.
Seminal paper introducing zero-inflated Poisson (ZIP) model for count data with excess zeros.
doi: 10.2307/1269547
[2]
Mullahy, J. (1986). Specification and testing of some modified count data models. Journal of Econometrics, 33(3), 341-365.
Introduced hurdle models as alternative to zero-inflated models for count data.
doi: 10.1016/0304-4076(86)90002-3
[3]
Vuong, Q. H. (1989). Likelihood ratio tests for model selection and non-nested hypotheses. Econometrica, 57(2), 307-333.
Vuong test for comparing non-nested models including ZIP vs Poisson, used extensively in zero-inflated modeling.
doi: 10.2307/1912557
[4]
Zeileis, A., Kleiber, C., & Jackman, S. (2008). Regression models for count data in R. Journal of Statistical Software, 27(8), 1-25.
Comprehensive guide to count data models in R including zero-inflated and hurdle models using pscl package.
doi: 10.18637/jss.v027.i08
[5]
Hilbe, J. M. (2011). Negative Binomial Regression (2nd ed.). Cambridge University Press.
Textbook covering negative binomial, zero-inflated, and hurdle models with extensive examples.
doi: 10.1017/CBO9780511973420
[6]
Cameron, A. C., & Trivedi, P. K. (2013). Regression Analysis of Count Data (2nd ed.). Cambridge University Press.
Definitive reference on count data regression including comprehensive treatment of zero-inflated models.
doi: 10.1017/CBO9781139013567
Zero is not just a number; it is a choice or a condition. If you don't model why the zeros exist, you are only telling half of the story.
The Interpretive Rigor Directive
statminds · Zero-InflatedMind reference · v2.2 · updated 2026-01-1715 of 15 sections