<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Andrea Di Francia</title>
<link>https://andreadifra.github.io/</link>
<atom:link href="https://andreadifra.github.io/index.xml" rel="self" type="application/rss+xml"/>
<description></description>
<generator>quarto-1.9.37</generator>
<lastBuildDate>Fri, 14 Aug 2026 00:00:00 GMT</lastBuildDate>
<item>
  <title>Zero-Inflated Models: A Practical Tutorial</title>
  <dc:creator>Andrea Di Francia</dc:creator>
  <link>https://andreadifra.github.io/posts/zero-inflated-models-tutorial/</link>
  <description><![CDATA[ 






<style>
.quarto-title-banner {
  background-color: rgba(6, 18, 34, 0.62);
  background-blend-mode: multiply;
  background-position: center;
  background-repeat: no-repeat;
}

/* Keep long equations inside the article column on narrow screens. MathJax
   containers are keyboard-focusable, so readers can scroll them directly. */
mjx-container[display="true"] {
  display: block;
  max-width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  padding-bottom: 0.25rem;
}

/* Allow long DOI and project URLs to wrap inside the bibliography rather than
   widening the full page on small screens. */
#refs a {
  overflow-wrap: anywhere;
}

</style>
<section id="introduction" class="level1" data-number="1">
<h1 data-number="1"><span class="header-section-number">1</span> Introduction</h1>
<p>In the past couple of years, I have worked with many healthcare datasets containing large numbers of zero outcomes. This problem is not unique to healthcare, but it can make standard count models difficult to apply. Zero-inflated models offer one flexible way to represent those data.</p>
<p>That flexibility also makes these models harder to implement and interpret. They receive less attention than many machine-learning methods, so I initially found it difficult to locate practical guidance that connected the theory, code, diagnostics, and interpretation.</p>
<p>This post grew out of the notes I made while applying zero-inflated models in industry, plus some of the internal training sessions I later ran on the topic. My goal is to provide a practical, hands-on guide to understanding and implementing zero-inflated models. There is some theory involved, but no background on this topic is necessary: the article builds up from ordinary count regression before introducing the two-process model.</p>
<p>This tutorial covers the theoretical foundations, practical implementation, model comparison, diagnostics, and interpretation of some of the simpler and more common zero-inflated count models. A follow-up tutorial may examine hurdle models, alternative count distributions, and more advanced validation strategies.</p>
<p>In terms of tooling, I strongly recommend the <code>glmmTMB</code> package in R, which is flexible, widely adopted, and well suited to the generalized linear model extensions used here. The Python ecosystem for this task is not quite as mature yet, although for standard applications the <code>statsmodels</code> library is a good starting point. The modelling sequence in this tutorial is simple enough and should be easily transferable if you decide to take that approach.</p>
<section id="what-are-zero-inflated-models" class="level2" data-number="1.1">
<h2 data-number="1.1" class="anchored" data-anchor-id="what-are-zero-inflated-models"><span class="header-section-number">1.1</span> What Are Zero-Inflated Models?</h2>
<p>In regression, zero-inflated models combine two components: a point mass at zero and a second distribution for the outcome. Predictors can enter both components through separate linear predictors and link functions. In this sense, zero-inflated regression models are technically defined as generalized linear mixture models.</p>
<p>Although they are often introduced for count data, the general framework is not limited to counts. For example, <span class="citation" data-cites="liu2019">Liu et al. (2019)</span> review zero-inflated models for non-negative continuous outcomes, while <span class="citation" data-cites="ospina2012">Ospina and Ferrari (2012)</span> develop zero-or-one-inflated beta regression for proportions.</p>
<p>This tutorial focuses on count data, where an observed count can arise from two distinct latent processes:</p>
<ol type="1">
<li>A latent extra-zero state, whose zeros are often called <strong>structural zeros</strong>.</li>
<li>A count-generating state, which produces <strong>sampling zeros</strong> as well as positive counts.</li>
</ol>
<p>What does this actually mean? Well, suppose you are counting clinic visits. A zero can mean at least two different things:</p>
<ul>
<li>the person was never really in a position to generate a visit during the study window</li>
<li>the person could have generated a visit, but happened not to</li>
</ul>
<p>A zero from the first route is called a <strong>structural zero</strong>; one from the second is a <strong>sampling zero</strong>. A standard one-process count model, such as Poisson regression, treats both people as coming from the same count-generating process. A zero-inflated model represents both routes as latent possibilities, but the data do not reveal which route produced any individual zero.</p>
</section>
<section id="when-do-we-need-zero-inflated-models" class="level2" data-number="1.2">
<h2 data-number="1.2" class="anchored" data-anchor-id="when-do-we-need-zero-inflated-models"><span class="header-section-number">1.2</span> When Do We Need Zero-Inflated Models?</h2>
<p>The key challenge zero-inflated models try to address is <strong>excess zeros</strong> in the data. However, the useful question is not “does my dataset contain a lot of zeros?”, but <strong>do the zeros plausibly come from more than one process?</strong></p>
<p>This distinction will become clearer in the following sections, but for now these are some helpful examples to keep in mind:</p>
<ul>
<li><strong>Healthcare use</strong>: Some patients are effectively unable to generate events because they never access services (structural zeros)—for example, people living in remote areas with no nearby clinics, or those excluded by policy or eligibility criteria. Other patients could use services but happen not to during the study window (sampling zeros)—for example, healthy patients who simply do not visit in that period or patients whose condition does not require care.</li>
<li><strong>Disease surveillance</strong>: Some locations truly have zero prevalence for a pathogen because the pathogen cannot survive there or has been eradicated (structural zeros). Other locations harbor the pathogen but a given survey fails to detect it during that sampling round (sampling zeros) — e.g., low prevalence or imperfect tests.</li>
<li><strong>Specialist treatments or prescriptions</strong>: Some patients will never be eligible for a specific specialist-only procedure or advanced drug (structural zeros) — think of treatments restricted by age, comorbidity, or insurance coverage. Other patients are eligible but simply don’t receive the treatment during the study window (sampling zeros) because they don’t yet need it, they defer care, or the treatment is rarely used in short follow-up.</li>
</ul>
<div id="fig-zero-sources" class="quarto-float quarto-figure quarto-figure-center anchored" alt="A hand-drawn flow diagram showing two possible routes to a healthcare count of zero: an extra-zero state associated with access or eligibility barriers, and ordinary non-use among people who could have attended.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-zero-sources-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://andreadifra.github.io/posts/zero-inflated-models-tutorial/figures/zero-sources.svg" class="img-fluid figure-img" alt="A hand-drawn flow diagram showing two possible routes to a healthcare count of zero: an extra-zero state associated with access or eligibility barriers, and ordinary non-use among people who could have attended.">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-zero-sources-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: Healthcare zeros can be interpreted through two possible latent routes: an extra-zero state associated with policy or access barriers, and ordinary non-use during the observation window.
</figcaption>
</figure>
</div>
<p>In each case, the zero may carry information about the process that generated the observation. That still leaves an important modelling caveat: excess zeros are not the same thing as proven structural zeros. A flexible one-process count model can sometimes reproduce many zeros without needing a separate latent class.</p>
</section>
</section>
<section id="theoretical-foundation-from-glms-to-mixture-models" class="level1" data-number="2">
<h1 data-number="2"><span class="header-section-number">2</span> Theoretical Foundation: From GLMs to Mixture Models</h1>
<section id="generalized-linear-models" class="level2" data-number="2.1">
<h2 data-number="2.1" class="anchored" data-anchor-id="generalized-linear-models"><span class="header-section-number">2.1</span> Generalized Linear Models</h2>
<p>Before fitting zero-inflated models, it helps to revisit <strong>generalized linear models</strong> (GLMs). Counts are non-negative integers, usually right-skewed, and often have variance that changes with the mean. Ordinary linear regression does not encode those features: it can predict negative values and assumes a constant-variance normal error structure. GLMs allow us to retain a regression-style mean model while using a response distribution suited to the outcome.</p>
<p>A GLM connects a linear predictor to the mean of an outcome distribution through a link function. Three ingredients define that structure:</p>
<ol type="1">
<li><strong>Linear predictor</strong> (<img src="https://latex.codecogs.com/png.latex?%5Ceta_i=X_i%5Cbeta">): a linear combination of predictor values and coefficients</li>
<li><strong>Link function</strong> (<img src="https://latex.codecogs.com/png.latex?g(%5Cmu_i)=%5Ceta_i">): the transformation connecting the linear predictor to the conditional mean</li>
<li><strong>Response distribution</strong>: a distribution suited to the outcome, such as Bernoulli for a binary response or Poisson for a count</li>
</ol>
<div id="fig-glm-pipeline" class="quarto-float quarto-figure quarto-figure-center anchored" alt="A hand-drawn left-to-right pipeline: predictors, linear predictor, link function, expected response, and observed outcome distribution.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-glm-pipeline-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://andreadifra.github.io/posts/zero-inflated-models-tutorial/figures/glm-pipeline.png" class="img-fluid figure-img" alt="A hand-drawn left-to-right pipeline: predictors, linear predictor, link function, expected response, and observed outcome distribution.">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-glm-pipeline-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: A generalized linear model turns predictors into a linear predictor, transforms it through a link function, and uses the result as the expected value for an observation model.
</figcaption>
</figure>
</div>
<p>Zero-inflated count models use this structure twice: a binary component models membership in the latent extra-zero group, and a count component models the expected outcome among observations in the count-generating group. The original zero-inflated Poisson regression paper framed this as a practical way to model excess zeros in manufacturing defects <span class="citation" data-cites="lambert1992">(Lambert 1992)</span>; the same idea now appears across health, ecology, insurance, and many other settings.</p>
<p>Logistic and Poisson regression provide the two building blocks. A short exponential-family refresher first recovers the logit link for a Bernoulli response; the following count-model section then applies the same logic to Poisson regression and its extensions.</p>
</section>
<section id="the-exponential-family" class="level2" data-number="2.2">
<h2 data-number="2.2" class="anchored" data-anchor-id="the-exponential-family"><span class="header-section-number">2.2</span> The Exponential Family</h2>
<p>The <strong>exponential family</strong> is a collection of probability distributions with a shared mathematical form. This might sound abstract, but it includes most distributions you encounter in practice: normal, Poisson, binomial, gamma, and many others.</p>
<p>A density or probability mass function in this family can be written as:</p>
<p><img src="https://latex.codecogs.com/png.latex?f(y%5Cmid%5Ctheta,%20%5Cphi)%20=%20%5Cexp%5Cleft%5C%7B%5Cfrac%7By%5Ctheta-b(%5Ctheta)%7D%7Ba(%5Cphi)%7D%20+%20c(y,%5Cphi)%5Cright%5C%7D."></p>
<p>The notation separates the parts that govern the distribution:</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?%5Ctheta"> is the <strong>natural parameter</strong>;</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Cphi"> is a <strong>dispersion parameter</strong>, with <img src="https://latex.codecogs.com/png.latex?a(%5Cphi)"> controlling its scale;</li>
<li><img src="https://latex.codecogs.com/png.latex?b(%5Ctheta)"> determines the mean and variance through its first two derivatives;</li>
<li><img src="https://latex.codecogs.com/png.latex?c(y,%5Cphi)"> supplies the remaining terms needed to define a valid distribution.</li>
</ul>
<p>Even though the formula looks daunting, the important part to keep in mind is that this format essentially <em>standardises</em> how we work with different distributions. In particular, it can be proved that for all distributions in this family, the mean and variance are:</p>
<p><img src="https://latex.codecogs.com/png.latex?E(Y)=b'(%5Ctheta),%20%5Cqquad%20%5Coperatorname%7BVar%7D(Y)=a(%5Cphi)b''(%5Ctheta)."></p>
<p>This common structure is what allows GLMs to pair different response distributions with a linear predictor. For a fuller treatment, McCullagh and Nelder give the classic mathematical account, while Dobson and Barnett provide a more introductory route through the same material <span class="citation" data-cites="mccullagh1989 dobson2018">(McCullagh and Nelder 1989; Dobson and Barnett 2018)</span>.</p>
<section id="the-bernoulli-distribution" class="level3" data-number="2.2.1">
<h3 data-number="2.2.1" class="anchored" data-anchor-id="the-bernoulli-distribution"><span class="header-section-number">2.2.1</span> The Bernoulli Distribution</h3>
<p>For a Bernoulli outcome <img src="https://latex.codecogs.com/png.latex?Y%5Cin%5C%7B0,1%5C%7D"> with success probability <img src="https://latex.codecogs.com/png.latex?p">,</p>
<p><img src="https://latex.codecogs.com/png.latex?f(y%5Cmid%20p)%20=%20p%5Ey(1-p)%5E%7B1-y%7D%0A=%20%5Cexp%5Cleft%5C%7By%5Clog%5Cleft(%5Cfrac%7Bp%7D%7B1-p%7D%5Cright)+%5Clog(1-p)%5Cright%5C%7D."></p>
<p>Writing the mass function this way identifies the natural parameter as</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctheta=%5Clog%5Cleft(%5Cfrac%7Bp%7D%7B1-p%7D%5Cright),"></p>
<p>also known as the logit of <img src="https://latex.codecogs.com/png.latex?p">. Bernoulli regression therefore uses the canonical logit link:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7Blogit%7D(p_i)=%5Clog%5Cleft(%5Cfrac%7Bp_i%7D%7B1-p_i%7D%5Cright)=X_i%5Cbeta."></p>
<p>The linear predictor <img src="https://latex.codecogs.com/png.latex?X_i%5Cbeta"> can take any real value, while the inverse-logit transformation keeps <img src="https://latex.codecogs.com/png.latex?p_i"> between 0 and 1.</p>
<p>Exponentiating a coefficient gives an odds ratio: <img src="https://latex.codecogs.com/png.latex?e%5E%7B%5Cbeta_j%7D"> is the multiplicative change in the odds for a one-unit increase in <img src="https://latex.codecogs.com/png.latex?x_j">, holding the other predictors fixed. For example, if <img src="https://latex.codecogs.com/png.latex?%5Cbeta_j=0.20">, then <img src="https://latex.codecogs.com/png.latex?e%5E%7B0.20%7D=1.22">, corresponding to a 22% higher odds for a one-unit increase in <img src="https://latex.codecogs.com/png.latex?x_j">. We will later use this same link to model the probability of latent extra-zero membership.</p>
<p>Changing the response distribution changes the canonical link and the variance assumption, but not the basic GLM architecture. We now make that transition from a binary response to a count response.</p>
</section>
</section>
<section id="count-model-building-blocks" class="level2" data-number="2.3">
<h2 data-number="2.3" class="anchored" data-anchor-id="count-model-building-blocks"><span class="header-section-number">2.3</span> Count-Model Building Blocks</h2>
<p>Poisson regression is the count-data counterpart to the Bernoulli example above: its exponential-family form produces a log link, while its response distribution supplies the mean-variance relationship. That separation matters because the link and the variance assumption can succeed or fail for different reasons.</p>
<p>The models therefore follow a deliberate sequence. We start with Poisson regression, check its conditional variance and zero predictions, move to negative binomial regression when the count process is overdispersed, and only then ask whether a separate zero-inflation process remains useful. Each step preserves the regression-style mean model while relaxing a specific distributional restriction.</p>
<section id="poisson-regression" class="level3" data-number="2.3.1">
<h3 data-number="2.3.1" class="anchored" data-anchor-id="poisson-regression"><span class="header-section-number">2.3.1</span> Poisson Regression</h3>
<p>Poisson regression is usually the standard first model for a count outcome. For person <img src="https://latex.codecogs.com/png.latex?i">, it assumes</p>
<p><img src="https://latex.codecogs.com/png.latex?Y_i%20%5Cmid%20X_i%20%5Csim%20%5Coperatorname%7BPoisson%7D(%5Clambda_i),%20%5Cqquad%20%5Clog(%5Clambda_i)%20=%20X_i%5Cbeta."></p>
<p>Its probability mass function has the exponential-family form</p>
<p><img src="https://latex.codecogs.com/png.latex?P(Y_i=y%5Cmid%20X_i)=%5Cfrac%7B%5Clambda_i%5Ey%20e%5E%7B-%5Clambda_i%7D%7D%7By!%7D%0A=%5Cexp%5Cleft%5C%7By%5Clog(%5Clambda_i)-%5Clambda_i-%5Clog(y!)%5Cright%5C%7D."></p>
<p>The natural parameter is therefore <img src="https://latex.codecogs.com/png.latex?%5Ctheta_i=%5Clog(%5Clambda_i)">, with <img src="https://latex.codecogs.com/png.latex?b(%5Ctheta_i)=e%5E%7B%5Ctheta_i%7D=%5Clambda_i">. The canonical log link keeps the expected count <img src="https://latex.codecogs.com/png.latex?%5Clambda_i"> positive. Exponentiating a regression coefficient gives a rate ratio: if <img src="https://latex.codecogs.com/png.latex?%5Cbeta_j=0.20">, then <img src="https://latex.codecogs.com/png.latex?e%5E%7B0.20%7D=1.22">, corresponding to a 22% higher expected count for a one-unit increase in <img src="https://latex.codecogs.com/png.latex?x_j">, holding the other predictors fixed. Notice the interpretation is different from the odds ratio in the Bernoulli case: …</p>
<p>The Poisson distribution has no estimated dispersion parameter, so <img src="https://latex.codecogs.com/png.latex?a(%5Cphi)=1"> in the general exponential-family form. Its derivative relationships are therefore</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Aa(%5Cphi)=1,%0A%5Cqquad%0Ab'(%5Ctheta_i)=b''(%5Ctheta_i)=e%5E%7B%5Ctheta_i%7D=%5Clambda_i,%0A"></p>
<p>and hence the Poisson mean–variance relationship</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AE(Y_i%20%5Cmid%20X_i)=%5Coperatorname%7BVar%7D(Y_i%20%5Cmid%20X_i)=%5Clambda_i.%0A"></p>
<p>This equality applies after conditioning on the predictors. Across the sample, people can have different values of <img src="https://latex.codecogs.com/png.latex?%5Clambda_i">, so combining their count distributions can produce a raw variance larger than the raw mean even when the conditional Poisson assumption holds. A large variance-to-mean ratio or a large number of zeros is therefore a warning, not evidence by itself of either conditional overdispersion or a separate zero-generating process. We assess those possibilities after fitting the Poisson mean model.</p>
</section>
<section id="overdispersion-and-negative-binomial-distribution" class="level3" data-number="2.3.2">
<h3 data-number="2.3.2" class="anchored" data-anchor-id="overdispersion-and-negative-binomial-distribution"><span class="header-section-number">2.3.2</span> Overdispersion and Negative Binomial Distribution</h3>
<p>Relative to a Poisson model, <strong>conditional overdispersion</strong> means</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Coperatorname%7BVar%7D(Y_i%5Cmid%20X_i)%3EE(Y_i%5Cmid%20X_i).%0A"></p>
<p>At a given conditional mean, an overdispersed count distribution is more spread out than the corresponding Poisson distribution. It places less probability near the mean and more in the tails, including at zero and at unusually large counts. An overdispersed one-process distribution can therefore reproduce zeros that a Poisson model misses without introducing a separate extra-zero group. Unobserved differences between people, an incomplete mean model, or dependence between observations can all produce this pattern. Whatever its source, unmodelled overdispersion makes Poisson standard errors too small and may leave too little fitted probability in both the lower and upper tails.</p>
<p>The negative binomial distribution tries to address this by adding an extra dispersion parameter. It allows us to keep the same log mean model,</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Clog(%5Cmu_i)%20=%20X_i%5Cbeta,"></p>
<p>but relaxes the Poisson variance assumption. <code>glmmTMB</code> provides two common negative-binomial parameterizations:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A%5Ctexttt%7Bnbinom1%7D:%5Cquad%0A%20%20%5Coperatorname%7BVar%7D(Y_i%5Cmid%20X_i)%20&amp;=%20%5Cmu_i(1+%5Calpha),%20%5C%5C%0A%5Ctexttt%7Bnbinom2%7D:%5Cquad%0A%20%20%5Coperatorname%7BVar%7D(Y_i%5Cmid%20X_i)%20&amp;=%20%5Cmu_i+%5Cfrac%7B%5Cmu_i%5E2%7D%7B%5Cphi%7D.%0A%5Cend%7Baligned%7D%0A"></p>
<p>In <code>nbinom1</code>, the additional variance <img src="https://latex.codecogs.com/png.latex?%5Calpha%5Cmu_i"> grows linearly with the mean, and the Poisson limit occurs as <img src="https://latex.codecogs.com/png.latex?%5Calpha%5Cto0">. In <code>nbinom2</code>, the additional variance <img src="https://latex.codecogs.com/png.latex?%5Cmu_i%5E2/%5Cphi"> grows quadratically, and the Poisson limit occurs as <img src="https://latex.codecogs.com/png.latex?%5Cphi%5Cto%5Cinfty">. The models fitted below use NB2 because its variance permits progressively greater spread at higher expected visit counts and because the zero-inflated negative binomial count component uses the same distribution. NB1 would remain plausible if the extra conditional variance increased approximately linearly with the mean.</p>
<p>NB2 also has a useful interpretation in terms of unobserved heterogeneity. Suppose counts are Poisson conditional on an individual event rate, but those rates vary according to a gamma distribution among people with the same observed predictors. Integrating over that variation gives the NB2 distribution, with <img src="https://latex.codecogs.com/png.latex?%5Cmu_i%5E2/%5Cphi"> measuring the additional variance due to differences in the underlying rates.</p>
<div class="callout callout-style-default callout-caution callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Caution</span>Mathematical details: NB2 in exponential-family form
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>For NB2, the conditional probability mass function is</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(Y_i=y%5Cmid%20X_i)%0A=%5Cfrac%7B%5CGamma(y+%5Cphi)%7D%7B%5CGamma(%5Cphi)y!%7D%0A%5Cleft(%5Cfrac%7B%5Cphi%7D%7B%5Cphi+%5Cmu_i%7D%5Cright)%5E%5Cphi%0A%5Cleft(%5Cfrac%7B%5Cmu_i%7D%7B%5Cphi+%5Cmu_i%7D%5Cright)%5Ey,%0A%5Cqquad%20y=0,1,2,%5Cldots.%0A"></p>
<p>For fixed <img src="https://latex.codecogs.com/png.latex?%5Cphi">, we can define</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Ctheta_i=%5Clog%5Cleft(%5Cfrac%7B%5Cmu_i%7D%7B%5Cmu_i+%5Cphi%7D%5Cright),%0A%5Cqquad%0Ab(%5Ctheta_i)=-%5Cphi%5Clog(1-e%5E%7B%5Ctheta_i%7D).%0A"></p>
<p>The mass function can then be written in exponential-family form as</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(Y_i=y%5Cmid%20X_i)%0A=%5Cexp%5Cleft%5C%7B%0A%20%20y%5Ctheta_i-b(%5Ctheta_i)%0A%20%20+%5Clog%5CGamma(y+%5Cphi)-%5Clog%5CGamma(%5Cphi)-%5Clog(y!)%0A%5Cright%5C%7D.%0A"></p>
<p>Differentiating <img src="https://latex.codecogs.com/png.latex?b(%5Ctheta_i)"> recovers the NB2 conditional moments:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AE(Y_i%5Cmid%20X_i)=b'(%5Ctheta_i)=%5Cmu_i,%0A%5Cqquad%0A%5Coperatorname%7BVar%7D(Y_i%5Cmid%20X_i)=b''(%5Ctheta_i)%0A=%5Cmu_i+%5Cfrac%7B%5Cmu_i%5E2%7D%7B%5Cphi%7D.%0A"></p>
</div>
</div>
</div>
<p>Because NB2 assigns more probability to zero than a Poisson distribution with the same mean, it may account for some of an observed zero surplus without a separate structural-zero process. The case study therefore fits NB2 as the stronger one-process baseline before introducing a separate extra-zero mechanism.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-2-contents" aria-controls="callout-2" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Generalized Poisson models
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-2" class="callout-2-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>Poisson and negative binomial models are not the only count-process choices. A generalized Poisson model is another way to relax the Poisson mean-variance relationship. In a common parameterization, let <img src="https://latex.codecogs.com/png.latex?%5Cdelta"> control dispersion and define</p>
<p><img src="https://latex.codecogs.com/png.latex?D%20=%20%5Cfrac%7B1%7D%7B(1-%5Cdelta)%5E2%7D."></p>
<p>For conditional mean <img src="https://latex.codecogs.com/png.latex?%5Cmu_i">, the variance is then</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7BVar%7D(Y_i%20%5Cmid%20X_i)%20=%20%5Cmu_iD%20=%20%5Cfrac%7B%5Cmu_i%7D%7B(1-%5Cdelta)%5E2%7D."></p>
<p>The ordinary Poisson model is recovered when <img src="https://latex.codecogs.com/png.latex?%5Cdelta=0"> and <img src="https://latex.codecogs.com/png.latex?D=1">. Positive <img src="https://latex.codecogs.com/png.latex?%5Cdelta"> gives <img src="https://latex.codecogs.com/png.latex?D%3E1"> and overdispersion; negative <img src="https://latex.codecogs.com/png.latex?%5Cdelta"> gives <img src="https://latex.codecogs.com/png.latex?D%3C1"> and underdispersion, subject to the admissible parameter range. In <code>glmmTMB</code>’s <code>genpois</code> family, the same variance is written as <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7BVar%7D(Y_i%5Cmid%20X_i)=%5Cmu_i%5Cphi_%7B%5Cmathrm%7BGP%7D%7D%5E2">. Thus <img src="https://latex.codecogs.com/png.latex?%5Cphi_%7B%5Cmathrm%7BGP%7D%7D%5E2"> is the index of dispersion—the same quantity denoted by <img src="https://latex.codecogs.com/png.latex?D"> above.</p>
<p>This mean-variance pattern differs from <code>nbinom2</code>. Generalized Poisson variance is proportional to <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> through <img src="https://latex.codecogs.com/png.latex?D">, whereas <code>nbinom2</code> adds the quadratic term <img src="https://latex.codecogs.com/png.latex?%5Cmu_i%5E2/%5Cphi">. I do not fit a generalized Poisson model here because the tutorial focuses on ZIP and ZINB, but it is a useful nearby option when the negative binomial variance pattern is a poor match.</p>
</div>
</div>
</div>
</section>
</section>
</section>
<section id="data-exploration-and-baseline-models" class="level1" data-number="3">
<h1 data-number="3"><span class="header-section-number">3</span> Data, Exploration, and Baseline Models</h1>
<p>Section 2 established the three main modelling possibilities carried into the case study: Poisson variation as a baseline, additional variation within a negative binomial count process, and a separate extra-zero process that can be combined with either count distribution. We now take those possibilities to the Medicare data. In general, it is good practice to progressively establish how and where more flexible one-process models fail, before implementing a two-process model.</p>
<div class="callout callout-style-simple callout-note callout-titled" title="Prerequisites">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-3-contents" aria-controls="callout-3" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Prerequisites
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-3" class="callout-3-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>Install the required packages before running the analysis:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Install packages if not already available</span></span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">install.packages</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb1-3">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"glmmTMB"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lme4"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DHARMa"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"performance"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"parameters"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ggplot2"</span>,</span>
<span id="cb1-4">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dplyr"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gridExtra"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"knitr"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"catdata"</span></span>
<span id="cb1-5">))</span></code></pre></div></div>
</div>
</div>
</div>
</div>
<section id="medicare-data-and-outcome" class="level2" data-number="3.1">
<h2 data-number="3.1" class="anchored" data-anchor-id="medicare-data-and-outcome"><span class="header-section-number">3.1</span> Medicare Data and Outcome</h2>
<p>The <code>medcare</code> dataset from the <code>catdata</code> package is a reduced teaching extract of the 4,406-person sample used by Deb and Trivedi, drawn from the 1987 National Medical Expenditure Survey <span class="citation" data-cites="schauberger2025 debtrivedi1997">(Schauberger and Tutz 2025; Deb and Trivedi 1997)</span>. It records healthcare use among people aged 66 and over who were covered by Medicare. The outcome, <code>ofp</code>, is each person’s number of physician office visits during the 1987 NMES observation year.</p>
<p>I like this example because the case for a zero-inflated model is not obvious from one very dramatic spike at zero. The data instead make us work through the same questions that often arise in the real world: how variable are the counts, which patients have no visits, and can a standard count model reproduce the observed zeros?</p>
<p>The extract omits survey weights, strata, and cluster identifiers, so the analysis treats the supplied records as independent and reports model-based rather than design-based uncertainty (for fuller provenance, assumptions, and software versions, jump ahead to Section&nbsp;6.3).</p>
<p>The analysis uses the following packages and variables:</p>
<div class="cell">
<details class="code-fold">
<summary>Show package-loading code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load required packages</span></span>
<span id="cb2-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(glmmTMB)</span>
<span id="cb2-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(lme4)</span>
<span id="cb2-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(DHARMa)</span>
<span id="cb2-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(performance)</span>
<span id="cb2-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(parameters)</span>
<span id="cb2-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb2-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span>
<span id="cb2-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(catdata)</span></code></pre></div></div>
</details>
</div>
<div class="cell">
<details class="code-fold">
<summary>Show data-loading code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load the medical care dataset</span></span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data</span>(medcare)</span>
<span id="cb3-3"></span>
<span id="cb3-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Examine the structure of the data</span></span>
<span id="cb3-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(medcare)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>  ofp hosp healthpoor healthexcellent numchron male age married school
1   5    1          0               0        2    1 6.9       1      6
2   1    0          0               0        2    0 7.4       1     10
3  13    3          1               0        4    0 6.6       0     10
4  16    1          1               0        2    1 7.6       1      3
5   3    0          0               0        2    0 7.9       1      6
6  17    0          1               0        5    0 6.6       0      7</code></pre>
</div>
<details class="code-fold">
<summary>Show data-loading code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glimpse</span>(medcare)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Rows: 4,406
Columns: 9
$ ofp             &lt;int&gt; 5, 1, 13, 16, 3, 17, 9, 3, 1, 0, 0, 44, 2, 1, 19, 19, …
$ hosp            &lt;int&gt; 1, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, …
$ healthpoor      &lt;int&gt; 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, …
$ healthexcellent &lt;int&gt; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ numchron        &lt;int&gt; 2, 2, 4, 2, 2, 5, 0, 0, 0, 0, 1, 5, 1, 1, 1, 0, 1, 2, …
$ male            &lt;int&gt; 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, …
$ age             &lt;dbl&gt; 6.9, 7.4, 6.6, 7.6, 7.9, 6.6, 7.5, 8.7, 7.3, 7.8, 6.6,…
$ married         &lt;int&gt; 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, …
$ school          &lt;int&gt; 6, 10, 10, 3, 6, 7, 8, 8, 8, 8, 8, 15, 8, 8, 12, 8, 8,…</code></pre>
</div>
</div>
<p>The variables used in this section are:</p>
<ul>
<li><code>ofp</code>: Number of physician office visits (our count outcome)</li>
<li><code>healthpoor</code>: Individual has poor health (reference: average health)</li>
<li><code>healthexcellent</code>: Individual has excellent health</li>
<li><code>numchron</code>: Number of chronic conditions</li>
<li><code>male</code>: Gender (female = 0, male = 1)</li>
<li><code>age</code>: Age in decades (<code>6.6</code> represents 66 years)</li>
<li><code>married</code>: Marital status (married = 1, else = 0)</li>
</ul>
</section>
<section id="distribution-of-visits-and-observed-zeros" class="level2" data-number="3.2">
<h2 data-number="3.2" class="anchored" data-anchor-id="distribution-of-visits-and-observed-zeros"><span class="header-section-number">3.2</span> Distribution of Visits and Observed Zeros</h2>
<p>The outcome summary keeps the sample size, centre, spread, and frequency of zeros in one place.</p>
<div class="cell">
<details class="code-fold">
<summary>Show summary table code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">stats_tbl <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb7-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Metric =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb7-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Participants"</span>,</span>
<span id="cb7-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Zero-visit records"</span>,</span>
<span id="cb7-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Proportion with zero visits"</span>,</span>
<span id="cb7-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Median visits"</span>,</span>
<span id="cb7-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mean visits"</span>,</span>
<span id="cb7-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Variance"</span>,</span>
<span id="cb7-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Variance-to-mean ratio"</span>,</span>
<span id="cb7-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Maximum visits"</span></span>
<span id="cb7-11">  ),</span>
<span id="cb7-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Value =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb7-13">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(medcare), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>),</span>
<span id="cb7-14">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ofp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>),</span>
<span id="cb7-15">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.1f%%"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ofp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)),</span>
<span id="cb7-16">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.0f"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ofp)),</span>
<span id="cb7-17">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ofp)),</span>
<span id="cb7-18">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">var</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ofp)),</span>
<span id="cb7-19">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">var</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ofp) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ofp)),</span>
<span id="cb7-20">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.0f"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ofp))</span>
<span id="cb7-21">  )</span>
<span id="cb7-22">)</span>
<span id="cb7-23"></span>
<span id="cb7-24">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(stats_tbl)</span></code></pre></div></div>
</details>
<div id="tbl-doctor-visit-summary" class="cell quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-doctor-visit-summary-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;1: Distribution of physician office visits (<code>ofp</code>).
</figcaption>
<div aria-describedby="tbl-doctor-visit-summary-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output-display">
<table class="cell caption-top table table-sm table-striped small">
<thead>
<tr class="header">
<th style="text-align: left;">Metric</th>
<th style="text-align: left;">Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Participants</td>
<td style="text-align: left;">4,406</td>
</tr>
<tr class="even">
<td style="text-align: left;">Zero-visit records</td>
<td style="text-align: left;">683</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Proportion with zero visits</td>
<td style="text-align: left;">15.5%</td>
</tr>
<tr class="even">
<td style="text-align: left;">Median visits</td>
<td style="text-align: left;">4</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Mean visits</td>
<td style="text-align: left;">5.77</td>
</tr>
<tr class="even">
<td style="text-align: left;">Variance</td>
<td style="text-align: left;">45.69</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Variance-to-mean ratio</td>
<td style="text-align: left;">7.91</td>
</tr>
<tr class="even">
<td style="text-align: left;">Maximum visits</td>
<td style="text-align: left;">89</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</div>
<p>There are three key insights we can draw from Table&nbsp;1:</p>
<ul>
<li><p>683 people (15.5%) have no recorded visits, and zero is the most frequent single count. That is a noticeable concentration, but its size alone does not establish zero-inflation. A Poisson or negative binomial distribution can also generate zeros.</p></li>
<li><p>The outcome is considerably right-skewed: the median is four visits, the mean is 5.77, and the maximum is 89 visits.</p></li>
<li><p>The variance is 7.91 times the mean. This <strong>marginal</strong> variance-to-mean ratio warns us that a Poisson model may be too restrictive, although the relevant assumption is conditional equidispersion after accounting for the predictors. We will test that on the fitted model rather than declaring overdispersion from the raw outcome alone.</p></li>
</ul>
<section id="zero-patterns-across-patient-characteristics" class="level3" data-number="3.2.1">
<h3 data-number="3.2.1" class="anchored" data-anchor-id="zero-patterns-across-patient-characteristics"><span class="header-section-number">3.2.1</span> Zero Patterns Across Patient Characteristics</h3>
<p>By exploring the distribution of zero-visit records, we notice that they are not distributed uniformly across the observed patient characteristics.</p>
<div class="cell">
<details class="code-fold">
<summary>Show visualization code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">p1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(medcare, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> ofp)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_histogram</span>(</span>
<span id="cb8-3">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">binwidth =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb8-4">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">boundary =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>,</span>
<span id="cb8-5">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#4C78A8"</span>,</span>
<span id="cb8-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span></span>
<span id="cb8-7">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_cartesian</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xlim =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">20.5</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb8-10">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Most participants recorded relatively few visits"</span>,</span>
<span id="cb8-11">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Physician office visits"</span>,</span>
<span id="cb8-12">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Participants"</span></span>
<span id="cb8-13">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>))</span>
<span id="cb8-16"></span>
<span id="cb8-17">health_zeros <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> medcare <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb8-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">health_status =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">case_when</span>(</span>
<span id="cb8-19">    healthpoor <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poor"</span>,</span>
<span id="cb8-20">    healthexcellent <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Excellent"</span>,</span>
<span id="cb8-21">    <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Average"</span></span>
<span id="cb8-22">  )) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb8-23">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(</span>
<span id="cb8-24">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">health_status =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(</span>
<span id="cb8-25">      health_status,</span>
<span id="cb8-26">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poor"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Average"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Excellent"</span>)</span>
<span id="cb8-27">    )</span>
<span id="cb8-28">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb8-29">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(health_status) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb8-30">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">prop_zeros =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(ofp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.groups =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"drop"</span>)</span>
<span id="cb8-31"></span>
<span id="cb8-32">p2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> health_zeros <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb8-33">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> health_status, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> prop_zeros)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-34">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_col</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#F58518"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-35">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(</span>
<span id="cb8-36">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%"</span>),</span>
<span id="cb8-37">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">limits =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.27</span>)</span>
<span id="cb8-38">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-39">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb8-40">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Zeros vary by reported health"</span>,</span>
<span id="cb8-41">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Self-reported health"</span>,</span>
<span id="cb8-42">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Zero-visit records"</span></span>
<span id="cb8-43">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-44">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-45">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>))</span>
<span id="cb8-46"></span>
<span id="cb8-47">chronic_zeros <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> medcare <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb8-48">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(numchron) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb8-49">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise</span>(</span>
<span id="cb8-50">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">prop_zeros =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(ofp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>),</span>
<span id="cb8-51">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">participants =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n</span>(),</span>
<span id="cb8-52">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.groups =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"drop"</span></span>
<span id="cb8-53">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb8-54">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(participants <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="cb8-55"></span>
<span id="cb8-56">p3 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> chronic_zeros <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb8-57">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> numchron, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> prop_zeros)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-58">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_col</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#54A24B"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.75</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-59">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_x_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> chronic_zeros<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>numchron) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-60">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(</span>
<span id="cb8-61">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> x), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%"</span>),</span>
<span id="cb8-62">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">limits =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.32</span>)</span>
<span id="cb8-63">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-64">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb8-65">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Zeros fall as chronic conditions increase"</span>,</span>
<span id="cb8-66">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chronic conditions"</span>,</span>
<span id="cb8-67">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Zero-visit records"</span></span>
<span id="cb8-68">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-69">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-70">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">face =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bold"</span>))</span>
<span id="cb8-71"></span>
<span id="cb8-72">gridExtra<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">grid.arrange</span>(</span>
<span id="cb8-73">  p1,</span>
<span id="cb8-74">  p2,</span>
<span id="cb8-75">  p3,</span>
<span id="cb8-76">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">layout_matrix =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span>
<span id="cb8-77">)</span></code></pre></div></div>
</details>
<div class="cell-output-display">
<div id="fig-zero-inflation-eda" class="quarto-float quarto-figure quarto-figure-center anchored" alt="A three-panel figure. The top panel shows a right-skewed histogram of office visits with zero as the most common count. The lower panels show that zero visits are most common among people reporting excellent health and become less common as the number of chronic conditions increases.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-zero-inflation-eda-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://andreadifra.github.io/posts/zero-inflated-models-tutorial/index_files/figure-html/fig-zero-inflation-eda-1.png" class="img-fluid figure-img" alt="A three-panel figure. The top panel shows a right-skewed histogram of office visits with zero as the most common count. The lower panels show that zero visits are most common among people reporting excellent health and become less common as the number of chronic conditions increases." width="960">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-zero-inflation-eda-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;3: Physician office visits and the distribution of zero-visit records across patient characteristics. The histogram is zoomed to 0–20 visits; 3.0% of observations lie above this range.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The descriptive pattern is clearest for chronic conditions. About 29% of people with no chronic conditions recorded zero visits, compared with 9% of those with two conditions and 6% of those with three. The final bars are based on smaller groups, so the overall decline matters more than every local change.</p>
<p>Self-reported health shows a less linear pattern. The zero proportion is highest for people reporting excellent health (24%), followed by average health (15%) and poor health (11%). These are unadjusted comparisons: age, sex, marital status, and chronic conditions differ between the groups. We therefore cannot read the bars as isolated health-status effects, still less as evidence that any particular zero is structural.</p>
<p>What the plots do establish is heterogeneity. The probability of a zero changes with observed patient characteristics, which makes a separate zero process plausible enough to investigate. It does not yet tell us whether a zero-inflated model will outperform an overdispersed one-process model.</p>
</section>
<section id="adjusted-associations-with-an-observed-zero" class="level3" data-number="3.2.2">
<h3 data-number="3.2.2" class="anchored" data-anchor-id="adjusted-associations-with-an-observed-zero"><span class="header-section-number">3.2.2</span> Adjusted Associations with an Observed Zero</h3>
<p>Collapsing the outcome to <strong>zero versus one or more visits</strong> allows an adjusted analysis of the observed zero pattern. This logistic regression is not the zero component of a fitted zero-inflated model and cannot identify which observed zeros are structural. It asks only whether the adjusted probability of recording no visits varies with the available predictors.</p>
<p>In applied work, I would use this step to start a conversation with domain experts. A coefficient can show that a group has more or fewer zero records after adjustment, but it cannot tell us whether those zeros arise from good health, poor access, avoidance, eligibility rules, or an omitted variable.</p>
<div class="cell">
<details class="code-fold">
<summary>Show logistic model code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create binary indicator: 1 = zero visits, 0 = any visits</span></span>
<span id="cb9-2">medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>no_visits <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ofp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb9-3"></span>
<span id="cb9-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Fit logistic regression</span></span>
<span id="cb9-5">logistic_model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glm</span>(</span>
<span id="cb9-6">  no_visits <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> healthpoor <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> healthexcellent <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> numchron <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> age <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> male <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> married,</span>
<span id="cb9-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> medcare,</span>
<span id="cb9-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">binomial</span>()</span>
<span id="cb9-9">)</span>
<span id="cb9-10"></span>
<span id="cb9-11">logistic_table <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model_parameters</span>(</span>
<span id="cb9-12">  logistic_model,</span>
<span id="cb9-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">exponentiate =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb9-14">) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb9-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(Parameter <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"(Intercept)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb9-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transmute</span>(</span>
<span id="cb9-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Predictor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">recode</span>(</span>
<span id="cb9-18">      Parameter,</span>
<span id="cb9-19">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">healthpoor =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poor vs average health"</span>,</span>
<span id="cb9-20">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">healthexcellent =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Excellent vs average health"</span>,</span>
<span id="cb9-21">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">numchron =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chronic conditions (per condition)"</span>,</span>
<span id="cb9-22">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">age =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Age (per decade)"</span>,</span>
<span id="cb9-23">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">male =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Male vs female"</span>,</span>
<span id="cb9-24">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">married =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Married vs not married"</span></span>
<span id="cb9-25">    ),</span>
<span id="cb9-26">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Odds ratio</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f"</span>, Coefficient),</span>
<span id="cb9-27">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">95% CI</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f–%.2f"</span>, CI_low, CI_high),</span>
<span id="cb9-28">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p-value</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">eps =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>)</span>
<span id="cb9-29">  )</span>
<span id="cb9-30"></span>
<span id="cb9-31">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(logistic_table, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"c"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>))</span></code></pre></div></div>
</details>
<div id="tbl-logistic-analysis" class="cell quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-logistic-analysis-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;2: Adjusted associations with recording zero physician office visits.
</figcaption>
<div aria-describedby="tbl-logistic-analysis-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output-display">
<table class="cell caption-top table table-sm table-striped small">
<thead>
<tr class="header">
<th style="text-align: left;">Predictor</th>
<th style="text-align: right;">Odds ratio</th>
<th style="text-align: center;">95% CI</th>
<th style="text-align: right;">p-value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Poor vs average health</td>
<td style="text-align: right;">1.22</td>
<td style="text-align: center;">0.89–1.65</td>
<td style="text-align: right;">0.204</td>
</tr>
<tr class="even">
<td style="text-align: left;">Excellent vs average health</td>
<td style="text-align: right;">1.24</td>
<td style="text-align: center;">0.94–1.62</td>
<td style="text-align: right;">0.129</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Chronic conditions (per condition)</td>
<td style="text-align: right;">0.58</td>
<td style="text-align: center;">0.53–0.63</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
<tr class="even">
<td style="text-align: left;">Age (per decade)</td>
<td style="text-align: right;">0.89</td>
<td style="text-align: center;">0.77–1.02</td>
<td style="text-align: right;">0.092</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Male vs female</td>
<td style="text-align: right;">1.70</td>
<td style="text-align: center;">1.42–2.04</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
<tr class="even">
<td style="text-align: left;">Married vs not married</td>
<td style="text-align: right;">0.64</td>
<td style="text-align: center;">0.53–0.78</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</div>
<p>Table&nbsp;2 shows that each additional chronic condition is associated with 42% lower odds of recording zero visits (odds ratio 0.58, 95% CI 0.53–0.63). Men have 70% higher odds of a zero than women, while married participants have 36% lower odds than those who are not married. These estimates describe associations conditional on the other variables; they do not establish causal effects.</p>
<p>The health-status coefficients point towards higher adjusted odds of a zero for both poor and excellent health, but the confidence intervals include 1. The data therefore do not support a clear adjusted health-status association in this specification. Likewise, the age estimate suggests that older cohorts have slightly lower odds of a zero, but its confidence interval also includes 1.</p>
<p>This difference between the descriptive plot and the adjusted model is useful rather than contradictory. The plot compares health groups as observed; the regression compares people with the same included covariates. Neither analysis identifies structural zeros.</p>
<p>Together with the descriptive plots, this model shows that zero outcomes have structure worth modelling and that their interpretation depends on the adjustment set.</p>
</section>
</section>
<section id="poisson-baseline" class="level2" data-number="3.3">
<h2 data-number="3.3" class="anchored" data-anchor-id="poisson-baseline"><span class="header-section-number">3.3</span> Poisson Baseline</h2>
<p>The standard starting point for count data is a Poisson regression. Even when we expect it to fail, this model provides a useful baseline:</p>
<ul>
<li>What relationships would a one-process count model estimate?</li>
<li>How badly does the variance assumption break?</li>
<li>How many zeros would this simpler model expect?</li>
</ul>
<p>For this application, the important Poisson assumptions are:</p>
<ol type="1">
<li><strong>Conditional distribution</strong>: Given the predictors, each person’s count follows a Poisson distribution.</li>
<li><strong>Conditional equidispersion</strong>: The conditional variance equals the conditional mean, <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BVar%7D(Y_i%20%5Cmid%20X_i)%20=%20E(Y_i%20%5Cmid%20X_i)"></li>
<li><strong>Independent records</strong>: Participants are independent after conditioning on the modelled predictors.</li>
<li><strong>Comparable exposure</strong>: Each count covers the same observation window; otherwise the model needs an exposure offset.</li>
</ol>
<p>We will first interpret the conditional-mean estimates, then check whether the Poisson variance and zero probabilities fit the data. Unlike the logistic model, which asked whether a person recorded no visits, the Poisson model uses the entire count and asks how the average number of visits changes with the predictors. It therefore provides a baseline model for the count process.</p>
<div class="cell">
<details class="code-fold">
<summary>Show Poisson model code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Fit Poisson model</span></span>
<span id="cb10-2">count_formula <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ofp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> healthpoor <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> healthexcellent <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> numchron <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-3">  age <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> male <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> married</span>
<span id="cb10-4"></span>
<span id="cb10-5">poisson_model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glm</span>(</span>
<span id="cb10-6">  count_formula,</span>
<span id="cb10-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> medcare,</span>
<span id="cb10-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">poisson</span>()</span>
<span id="cb10-9">)</span>
<span id="cb10-10"></span>
<span id="cb10-11">poisson_table <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model_parameters</span>(</span>
<span id="cb10-12">  poisson_model,</span>
<span id="cb10-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">exponentiate =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb10-14">) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb10-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(Parameter <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"(Intercept)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb10-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transmute</span>(</span>
<span id="cb10-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Predictor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">recode</span>(</span>
<span id="cb10-18">      Parameter,</span>
<span id="cb10-19">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">healthpoor =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poor vs average health"</span>,</span>
<span id="cb10-20">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">healthexcellent =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Excellent vs average health"</span>,</span>
<span id="cb10-21">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">numchron =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chronic conditions (per condition)"</span>,</span>
<span id="cb10-22">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">age =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Age (per decade)"</span>,</span>
<span id="cb10-23">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">male =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Male vs female"</span>,</span>
<span id="cb10-24">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">married =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Married vs not married"</span></span>
<span id="cb10-25">    ),</span>
<span id="cb10-26">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Rate ratio</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f"</span>, Coefficient),</span>
<span id="cb10-27">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">95% CI</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f–%.2f"</span>, CI_low, CI_high),</span>
<span id="cb10-28">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p-value</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">eps =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>)</span>
<span id="cb10-29">  )</span>
<span id="cb10-30"></span>
<span id="cb10-31">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(poisson_table, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"c"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>))</span></code></pre></div></div>
</details>
<div id="tbl-poisson-analysis" class="cell quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-poisson-analysis-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;3: Poisson regression estimates for physician office visits.
</figcaption>
<div aria-describedby="tbl-poisson-analysis-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output-display">
<table class="cell caption-top table table-sm table-striped small">
<thead>
<tr class="header">
<th style="text-align: left;">Predictor</th>
<th style="text-align: right;">Rate ratio</th>
<th style="text-align: center;">95% CI</th>
<th style="text-align: right;">p-value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Poor vs average health</td>
<td style="text-align: right;">1.29</td>
<td style="text-align: center;">1.25–1.33</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
<tr class="even">
<td style="text-align: left;">Excellent vs average health</td>
<td style="text-align: right;">0.70</td>
<td style="text-align: center;">0.66–0.75</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Chronic conditions (per condition)</td>
<td style="text-align: right;">1.18</td>
<td style="text-align: center;">1.17–1.19</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
<tr class="even">
<td style="text-align: left;">Age (per decade)</td>
<td style="text-align: right;">0.95</td>
<td style="text-align: center;">0.93–0.97</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Male vs female</td>
<td style="text-align: right;">0.90</td>
<td style="text-align: center;">0.88–0.93</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
<tr class="even">
<td style="text-align: left;">Married vs not married</td>
<td style="text-align: right;">1.00</td>
<td style="text-align: center;">0.97–1.03</td>
<td style="text-align: right;">0.93</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</div>
<p>Table&nbsp;3 presents the results of the Poisson regression. As a quick reminder, a Poisson rate ratio describes a proportional difference in the expected count: the average number of visits predicted for people with the same included characteristics.</p>
<p>Here, under the Poisson mean model, poor health is associated with a 29% higher expected visit count than average health, while excellent health is associated with a 30% lower count. Each additional chronic condition is associated with an 18% increase. Men have an expected count about 10% lower than women, and a decade of age is associated with a 5% reduction. The estimate for marital status is essentially null.</p>
</section>
<section id="where-the-poisson-model-fails" class="level2" data-number="3.4">
<h2 data-number="3.4" class="anchored" data-anchor-id="where-the-poisson-model-fails"><span class="header-section-number">3.4</span> Where the Poisson Model Fails</h2>
<p>The fitted mean structure does not establish that the Poisson distribution describes the conditional variation. The Pearson residuals provide a direct assessment of equidispersion after adjustment for the predictors.</p>
<div class="cell">
<details class="code-fold">
<summary>Show overdispersion diagnostic code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1">overdispersion_check <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">check_overdispersion</span>(poisson_model)</span>
<span id="cb11-2"></span>
<span id="cb11-3">overdispersion_table <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb11-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Metric =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb11-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Pearson chi-squared"</span>,</span>
<span id="cb11-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Residual degrees of freedom"</span>,</span>
<span id="cb11-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Dispersion ratio"</span>,</span>
<span id="cb11-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p-value"</span></span>
<span id="cb11-9">  ),</span>
<span id="cb11-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Value =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb11-11">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(</span>
<span id="cb11-12">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(overdispersion_check<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>chisq_statistic),</span>
<span id="cb11-13">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span></span>
<span id="cb11-14">    ),</span>
<span id="cb11-15">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(</span>
<span id="cb11-16">      overdispersion_check<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>residual_df,</span>
<span id="cb11-17">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span></span>
<span id="cb11-18">    ),</span>
<span id="cb11-19">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f"</span>, overdispersion_check<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>dispersion_ratio),</span>
<span id="cb11-20">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(overdispersion_check<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p_value, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">eps =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>)</span>
<span id="cb11-21">  )</span>
<span id="cb11-22">)</span>
<span id="cb11-23"></span>
<span id="cb11-24">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(overdispersion_table)</span></code></pre></div></div>
</details>
<div id="tbl-poisson-overdispersion" class="cell quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-poisson-overdispersion-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;4: Pearson overdispersion diagnostic for the Poisson model.
</figcaption>
<div aria-describedby="tbl-poisson-overdispersion-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output-display">
<table class="cell caption-top table table-sm table-striped small">
<thead>
<tr class="header">
<th style="text-align: left;">Metric</th>
<th style="text-align: left;">Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Pearson chi-squared</td>
<td style="text-align: left;">31,664</td>
</tr>
<tr class="even">
<td style="text-align: left;">Residual degrees of freedom</td>
<td style="text-align: left;">4,399</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Dispersion ratio</td>
<td style="text-align: left;">7.20</td>
</tr>
<tr class="even">
<td style="text-align: left;">p-value</td>
<td style="text-align: left;">&lt;0.001</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</div>
<div class="callout callout-style-default callout-tip callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Tip</span>What is overdispersion?
</div>
</div>
<div class="callout-body-container callout-body">
<p>Remember that overdispersion occurs when the conditional variance of the observed counts exceeds the variance allowed by the model. For a Poisson model, the conditional mean and variance must be equal. A dispersion ratio substantially above 1 indicates that this assumption is inadequate.</p>
</div>
</div>
<p>The dispersion ratio is 7.20, well above the value of 1 expected under a Poisson model. The observed visit counts therefore vary much more than the model permits under the Poisson assumption. This overdispersion makes the model-based standard errors too small and the corresponding confidence intervals and p-values too optimistic. The rate ratios still summarize the fitted mean structure, but this means that the Poisson model does not provide reliable inference for these data.</p>
<p>Overdispersion identifies the Poisson model as inadequate but does not identify the source of the extra variation. The next one-process candidate is therefore negative binomial regression, which relaxes equidispersion without introducing a latent extra-zero group.</p>
</section>
<section id="negative-binomial-fit-and-zero-frequency-comparison" class="level2" data-number="3.5">
<h2 data-number="3.5" class="anchored" data-anchor-id="negative-binomial-fit-and-zero-frequency-comparison"><span class="header-section-number">3.5</span> Negative-Binomial Fit and Zero-Frequency Comparison</h2>
<p>The negative binomial baseline retains <code>count_formula</code>, so it makes the same conditional comparisons as the Poisson model. Its <code>nbinom2</code> variance, <img src="https://latex.codecogs.com/png.latex?%5Cmu_i%20+%20%5Cmu_i%5E2/%5Cphi">, allows variation to increase faster than the mean.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">nb_model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmmTMB</span>(</span>
<span id="cb12-2">  count_formula,</span>
<span id="cb12-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> medcare,</span>
<span id="cb12-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nbinom2</span>()</span>
<span id="cb12-5">)</span></code></pre></div></div>
</div>
<p>The fitted dispersion parameter is <img src="https://latex.codecogs.com/png.latex?%5Chat%7B%5Cphi%7D%20="> 1.13. This finite value allows substantially more conditional variation than Poisson; the Poisson limit would require <img src="https://latex.codecogs.com/png.latex?%5Cphi%20%5Cto%20%5Cinfty">. The model still treats every participant as arising from one count-generating process.</p>
<p>Zero prediction isolates one important consequence of the different variance assumptions. For participant <img src="https://latex.codecogs.com/png.latex?i">, the fitted Poisson probability of zero is</p>
<p><img src="https://latex.codecogs.com/png.latex?P(Y_i%20=%200)%20=%20e%5E%7B-%5Chat%7B%5Clambda%7D_i%7D"></p>
<p>whereas the fitted NB2 probability is</p>
<p><img src="https://latex.codecogs.com/png.latex?P(Y_i%20=%200)%20=%20%5Cleft(%5Cfrac%7B%5Chat%7B%5Cphi%7D%7D%7B%5Chat%7B%5Cphi%7D+%5Chat%7B%5Cmu%7D_i%7D%5Cright)%5E%7B%5Chat%7B%5Cphi%7D%7D."></p>
<p>Summing the person-specific probabilities gives the expected number of zero-visit records under each model.</p>
<div class="cell">
<details class="code-fold">
<summary>Show zero-frequency comparison code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Observed zeros</span></span>
<span id="cb13-2">observed_zeros <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ofp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb13-3"></span>
<span id="cb13-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Predicted zeros from Poisson model</span></span>
<span id="cb13-5">poisson_pred <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predict</span>(poisson_model, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"response"</span>)</span>
<span id="cb13-6">poisson_zero_prob <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>poisson_pred)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># P(Y=0) for Poisson</span></span>
<span id="cb13-7">expected_zeros_poisson <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(poisson_zero_prob)</span>
<span id="cb13-8"></span>
<span id="cb13-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Predicted zeros from negative binomial model</span></span>
<span id="cb13-10">nb_mean <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predict</span>(nb_model, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"conditional"</span>)</span>
<span id="cb13-11">nb_dispersion <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predict</span>(nb_model, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"disp"</span>)</span>
<span id="cb13-12">nb_zero_prob <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dnbinom</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mu =</span> nb_mean, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> nb_dispersion)</span>
<span id="cb13-13">expected_zeros_nb <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(nb_zero_prob)</span>
<span id="cb13-14"></span>
<span id="cb13-15">zero_comparison <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb13-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Model =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poisson"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Negative binomial (NB2)"</span>),</span>
<span id="cb13-17">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Expected zeros</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb13-18">    expected_zeros_poisson,</span>
<span id="cb13-19">    expected_zeros_nb</span>
<span id="cb13-20">  )),</span>
<span id="cb13-21">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Observed minus expected</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> observed_zeros <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Expected zeros</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>,</span>
<span id="cb13-22">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Expected / observed</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(</span>
<span id="cb13-23">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.1f%%"</span>,</span>
<span id="cb13-24">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Expected zeros</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> observed_zeros</span>
<span id="cb13-25">  )</span>
<span id="cb13-26">)</span>
<span id="cb13-27"></span>
<span id="cb13-28">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(</span>
<span id="cb13-29">  zero_comparison,</span>
<span id="cb13-30">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>)</span>
<span id="cb13-31">)</span></code></pre></div></div>
</details>
<div id="tbl-zero-comparison" class="cell quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-zero-comparison-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;5: Zeros expected from the fitted one-process models. The data contain 683 observed zero-visit records.
</figcaption>
<div aria-describedby="tbl-zero-comparison-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output-display">
<table class="cell caption-top table table-sm table-striped small">
<colgroup>
<col style="width: 28%">
<col style="width: 18%">
<col style="width: 28%">
<col style="width: 24%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">Model</th>
<th style="text-align: right;">Expected zeros</th>
<th style="text-align: right;">Observed minus expected</th>
<th style="text-align: right;">Expected / observed</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Poisson</td>
<td style="text-align: right;">37</td>
<td style="text-align: right;">646</td>
<td style="text-align: right;">5.4%</td>
</tr>
<tr class="even">
<td style="text-align: left;">Negative binomial (NB2)</td>
<td style="text-align: right;">623</td>
<td style="text-align: right;">60</td>
<td style="text-align: right;">91.2%</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</div>
<p>The fitted Poisson model expects approximately 37 zero-visit records, only 5.4% of the 683 observed. NB2 expects approximately 623, or 91.2% of the observed number. Allowing extra variation within one count process therefore explains most of what initially looked like a zero surplus.</p>
<p>The remaining shortfall is about 60 zero records. That discrepancy keeps a separate extra-zero process under consideration, but it does not prove that such a process exists. Misspecification of the conditional mean, other forms of heterogeneity, or a different count distribution could also affect zero prediction.</p>
<p>The baseline analysis has therefore narrowed rather than settled the question. Poisson is too restrictive, while NB2 captures most of the dispersion and zero frequency without a latent class. Section 4 introduces the extra-zero mechanism so that its additional structure can be compared with this stronger one-process benchmark.</p>
</section>
</section>
<section id="how-zero-inflated-models-work" class="level1" data-number="4">
<h1 data-number="4"><span class="header-section-number">4</span> How Zero-Inflated Models Work</h1>
<section id="a-latent-two-process-model" class="level2" data-number="4.1">
<h2 data-number="4.1" class="anchored" data-anchor-id="a-latent-two-process-model"><span class="header-section-number">4.1</span> A Latent Two-Process Model</h2>
<p>Unlike the negative binomial baseline, which keeps every participant in one count process, a zero-inflated model allows either of two states to generate each observed count. For participant <img src="https://latex.codecogs.com/png.latex?i">, we introduce <img src="https://latex.codecogs.com/png.latex?S_i"> as a binary indicator of that state.</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?S_i=1"> means the <strong>extra-zero state</strong> is active. In this state, the recorded number of visits must be zero.</li>
<li><img src="https://latex.codecogs.com/png.latex?S_i=0"> means the <strong>count-generating state</strong> is active. This state can produce either zero visits or a positive number of visits.</li>
</ul>
<p>The state is <em>latent</em> because it is not recorded in the data. When a participant has zero visits, we do not know which state generated that zero. The idea is to model the probability that an individual patient will fall under each state.</p>
<p>This probability may vary across patient profiles. Let <img src="https://latex.codecogs.com/png.latex?Z_i"> contain the predictors used for this part of the model, and let <img src="https://latex.codecogs.com/png.latex?%5Cpi_i"> be the resulting probability that participant <img src="https://latex.codecogs.com/png.latex?i"> is in the extra-zero state. We write</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0AS_i%20%5Cmid%20Z_i%20&amp;%5Csim%20%5Coperatorname%7BBernoulli%7D(%5Cpi_i),%20%5C%5C%0AP(S_i=1%5Cmid%20Z_i)%20&amp;=%20%5Cpi_i.%0A%5Cend%7Baligned%7D%0A"></p>
<p>In other words, <img src="https://latex.codecogs.com/png.latex?S_i"> takes the value 1 with probability <img src="https://latex.codecogs.com/png.latex?%5Cpi_i">, based on the participant’s zero-inflation predictors <img src="https://latex.codecogs.com/png.latex?Z_i">.</p>
<p>Now let <img src="https://latex.codecogs.com/png.latex?Y_i"> be the observed number of visits and let <img src="https://latex.codecogs.com/png.latex?X_i"> contain the predictors used for the count component. The outcome model formalizes the two states described above:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0AY_i%20%5Cmid%20S_i=1%20&amp;%5Cequiv%200,%20%5C%5C%0AY_i%20%5Cmid%20S_i=0,X_i%20&amp;%5Csim%20f_c(%5C,%5Ccdot%5C,;%5Cmu_i,%5Cpsi).%0A%5Cend%7Baligned%7D%0A"></p>
<p>When the extra-zero state is active, by definition the number of visits must be zero. In the count-generating state, visits follow <img src="https://latex.codecogs.com/png.latex?f_c">, a count distribution with mean <img src="https://latex.codecogs.com/png.latex?%5Cmu_i">. The placeholder <img src="https://latex.codecogs.com/png.latex?%5Cpsi"> represents a family-specific dispersion parameter when one is required: it is absent for Poisson and equals <img src="https://latex.codecogs.com/png.latex?%5Cphi"> for the NB2 model used later.</p>
<p>In essence, and forgetting about notation for a moment, the central idea is that the extra-zero state always produces zero, whereas the count-generating state can produce either zero or a positive count. Figure&nbsp;4 illustrates this two-stage process.</p>
<div id="fig-zero-inflated-process" class="quarto-float quarto-figure quarto-figure-center anchored" alt="A hand-drawn two-stage model diagram: a patient record enters a zero-inflation process, which can produce an extra zero or pass the record to a count process that can produce zero or one or more visits.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-zero-inflated-process-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://andreadifra.github.io/posts/zero-inflated-models-tutorial/figures/zero-inflated-process.svg" class="img-fluid figure-img" alt="A hand-drawn two-stage model diagram: a patient record enters a zero-inflation process, which can produce an extra zero or pass the record to a count process that can produce zero or one or more visits.">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-zero-inflated-process-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;4: A zero-inflated model assigns probability to a latent extra-zero state and uses a count process for observations outside that state.
</figcaption>
</figure>
</div>
<p>For the Medicare data, the two components therefore ask different questions. The zero-inflation component asks which patient profiles receive a higher probability of the extra-zero state. The count component asks how expected visits change within the count-generating state.</p>
</section>
<section id="mixture-probabilities-and-likelihood" class="level2" data-number="4.2">
<h2 data-number="4.2" class="anchored" data-anchor-id="mixture-probabilities-and-likelihood"><span class="header-section-number">4.2</span> Mixture Probabilities and Likelihood</h2>
<p>Zeros are ambiguous because either latent state can produce them. Positive counts are not: they can come only from the count-generating state. This asymmetry gives the model information about both components. It estimates them jointly from all observations rather than classifying the zeros first and then fitting separate regressions.</p>
<p>Let <img src="https://latex.codecogs.com/png.latex?f_c(k;%5Cmu_i,%5Cpsi)"> denote the probability that the count component assigns to the value <img src="https://latex.codecogs.com/png.latex?k">. The possible routes are:</p>
<ul>
<li>If <img src="https://latex.codecogs.com/png.latex?y_i=0">, the observation may come directly from the extra-zero state, with probability <img src="https://latex.codecogs.com/png.latex?%5Cpi_i">, or from the count-generating state producing zero, with probability <img src="https://latex.codecogs.com/png.latex?(1-%5Cpi_i)f_c(0;%5Cmu_i,%5Cpsi)">.</li>
<li>If <img src="https://latex.codecogs.com/png.latex?y_i%3E0">, the observation has one possible route: the count-generating state, with probability <img src="https://latex.codecogs.com/png.latex?(1-%5Cpi_i)f_c(y_i;%5Cmu_i,%5Cpsi)">.</li>
</ul>
<p>The likelihood contribution <img src="https://latex.codecogs.com/png.latex?L_i"> is the probability that the model assigns to the outcome observed for participant <img src="https://latex.codecogs.com/png.latex?i">. The two cases above give</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AL_i(%5Cpi_i,%5Cmu_i,%5Cpsi)%0A=%0A%5Cbegin%7Bcases%7D%0A%5Cpi_i+(1-%5Cpi_i)f_c(0;%5Cmu_i,%5Cpsi),%20&amp;%20y_i=0,%20%5C%5C%0A(1-%5Cpi_i)f_c(y_i;%5Cmu_i,%5Cpsi),%20&amp;%20y_i%3E0.%0A%5Cend%7Bcases%7D%0A"></p>
<p>In each case, <img src="https://latex.codecogs.com/png.latex?L_i"> is the probability that the model assigns to participant <img src="https://latex.codecogs.com/png.latex?i">’s observed outcome. For a zero, the contribution adds the probabilities of both routes instead of choosing one. Across the sample, these contributions form a single objective for estimating the count, zero-inflation, and dispersion parameters together.</p>
<div class="callout callout-style-default callout-caution callout-titled" title="The full likelihood">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-5-contents" aria-controls="callout-5" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Caution</span>The full likelihood
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-5" class="callout-5-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>Multiplying the contributions from all <img src="https://latex.codecogs.com/png.latex?n"> participants gives the full likelihood. The coefficient vectors <img src="https://latex.codecogs.com/png.latex?%5Cbeta"> and <img src="https://latex.codecogs.com/png.latex?%5Cgamma"> govern the count and zero-inflation components, respectively:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AL(%5Cbeta,%5Cgamma,%5Cpsi)%0A=%0A%5Cprod_%7Bi=1%7D%5E%7Bn%7D%0AL_i%5Cbigl(%5Cpi_i(%5Cgamma),%5Cmu_i(%5Cbeta),%5Cpsi%5Cbigr).%0A"></p>
<p>Maximizing this product estimates the count, zero-inflation, and dispersion parameters jointly.</p>
</div>
</div>
</div>
<p>Joint estimation also explains why the preliminary logistic regression in Table&nbsp;2 is not the fitted zero-inflation component. The preliminary regression models the observed event <img src="https://latex.codecogs.com/png.latex?Y_i=0">, regardless of which state produced the zero. The fitted zero-inflation component models the latent event <img src="https://latex.codecogs.com/png.latex?S_i=1">. These are different outcomes: the probability of an observed zero includes both routes, whereas <img src="https://latex.codecogs.com/png.latex?%5Cpi_i"> is the model probability of the extra-zero state.</p>
<p>Because the state remains unobserved, a zero raises the practical question: given that we observed a zero, what is the probability that it came from the extra-zero state rather than from the count-generating state? The posterior probability below answers that question. Bayes’ rule first expresses it in terms of model probabilities:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0AP(S_i=1%5Cmid%20Y_i=0,X_i,Z_i)%0A&amp;=%0A%5Cfrac%7B%0AP(Y_i=0%5Cmid%20S_i=1)P(S_i=1%5Cmid%20Z_i)%0A%7D%7B%0AP(Y_i=0%5Cmid%20X_i,Z_i)%0A%7D%20%5C%5C%0A&amp;=%0A%5Cfrac%7B%0A1%5Ctimes%5Cpi_i%0A%7D%7B%0A%5Cpi_i+(1-%5Cpi_i)f_c(0;%5Cmu_i,%5Cpsi)%0A%7D.%0A%5Cend%7Baligned%7D%0A"></p>
<p>The first numerator term equals one because the extra-zero state always produces zero. The prior model probability of that state is <img src="https://latex.codecogs.com/png.latex?%5Cpi_i"> by definition of the zero-inflation component. The denominator contains both routes to an observed zero: the extra-zero route and a zero from the count-generating state. For a positive count, the posterior probability of the extra-zero state is zero because that state cannot produce a positive value.</p>
<p>For a concrete example with a Poisson count component, suppose the model assigns observations with a particular covariate profile an extra-zero probability <img src="https://latex.codecogs.com/png.latex?%5Cpi_i=0.15"> and a count-component mean <img src="https://latex.codecogs.com/png.latex?%5Clambda_i=3.2">.</p>
<ul>
<li>Within the count-generating state, the probability of zero visits is <img src="https://latex.codecogs.com/png.latex?e%5E%7B-3.2%7D=0.041">, or 4.1%.</li>
<li>Combining both routes gives an overall zero probability of <img src="https://latex.codecogs.com/png.latex?0.15+0.85(0.041)=0.185">, or 18.5%.</li>
<li>If an observation with this profile equals zero, the posterior probability of the extra-zero state is <img src="https://latex.codecogs.com/png.latex?0.15/0.185%5Capprox0.81">, or 81%.</li>
</ul>
<p>This posterior probability therefore updates uncertainty about the latent state. Because the count component considers zero unlikely for this profile, observing zero shifts much of the model’s probability toward the extra-zero state. This soft assignment helps estimate the two components jointly.</p>
</section>
<section id="mixture-mean-and-variance" class="level2" data-number="4.3">
<h2 data-number="4.3" class="anchored" data-anchor-id="mixture-mean-and-variance"><span class="header-section-number">4.3</span> Mixture Mean and Variance</h2>
<p>Once the model has estimated the extra-zero probability and the behaviour of the count-generating state, we can ask what it predicts for observed visits. Here, <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> is the mean of the chosen count distribution for participant <img src="https://latex.codecogs.com/png.latex?i"> within the count-generating state. Let <img src="https://latex.codecogs.com/png.latex?V_c(%5Cmu_i)"> denote the corresponding variance:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0AE(Y_i%5Cmid%20S_i=0,X_i)%20&amp;=%20%5Cmu_i,%20%5C%5C%0A%5Coperatorname%7BVar%7D(Y_i%5Cmid%20S_i=0,X_i)%20&amp;=%20V_c(%5Cmu_i).%0A%5Cend%7Baligned%7D%0A"></p>
<p>In a single-process count model, <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> would also be the expected observed count. In a zero-inflated model, however, the model assigns some probability to an always-zero state. We must average over both states to obtain expected observed visits.</p>
<p>The extra-zero state contributes zero with probability <img src="https://latex.codecogs.com/png.latex?%5Cpi_i">, while the count-generating state contributes an average of <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> with probability <img src="https://latex.codecogs.com/png.latex?1-%5Cpi_i">. Therefore,</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AE(Y_i%5Cmid%20X_i,Z_i)%0A=%5Cpi_i(0)+(1-%5Cpi_i)%5Cmu_i%0A=(1-%5Cpi_i)%5Cmu_i.%0A"></p>
<p>This <strong>conditional mixture mean</strong> is conditional on the observed predictors <img src="https://latex.codecogs.com/png.latex?X_i"> and <img src="https://latex.codecogs.com/png.latex?Z_i">, but averages over the unobserved state <img src="https://latex.codecogs.com/png.latex?S_i">. It is the quantity we need when comparing expected visits across patient profiles. Reporting <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> instead would describe only the count-generating state and would overstate expected observed visits whenever <img src="https://latex.codecogs.com/png.latex?%5Cpi_i%3E0">.</p>
<p>The mean alone does not tell us how observations are distributed around that average. Two fitted distributions can predict the same expected number of visits while assigning very different probabilities to zero, moderate, and high counts. The mixture variance summarizes this spread, so it helps us judge whether the fitted distribution represents the observed pattern of visits.</p>
<div class="callout callout-style-default callout-caution callout-titled" title="Deriving the mixture variance">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-6-contents" aria-controls="callout-6" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Caution</span>Deriving the mixture variance
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-6" class="callout-6-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>The <a href="https://en.wikipedia.org/wiki/Law_of_total_variance">law of total variance</a> separates variation within the latent states from variation between their conditional means.</p>
<p><strong>Within-state variation</strong> is the variation that remains after fixing the latent state. The extra-zero state contributes no variance because it always produces zero. The count-generating state contributes <img src="https://latex.codecogs.com/png.latex?V_c(%5Cmu_i)"> and occurs with probability <img src="https://latex.codecogs.com/png.latex?1-%5Cpi_i">. Therefore,</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bgathered%7D%0AE%5C!%5Cleft%5B%0A%5Coperatorname%7BVar%7D(Y_i%5Cmid%20S_i,X_i,Z_i)%0A%5Cright%5D%20%5C%5C%0A=%5Cpi_i(0)+(1-%5Cpi_i)V_c(%5Cmu_i)%20%5C%5C%0A=(1-%5Cpi_i)V_c(%5Cmu_i).%0A%5Cend%7Bgathered%7D%0A"></p>
<p><strong>Between-state variation</strong> arises because the states have different means: zero in the extra-zero state and <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> in the count-generating state. The state-specific mean can be written as <img src="https://latex.codecogs.com/png.latex?%5Cmu_i(1-S_i)">. Because <img src="https://latex.codecogs.com/png.latex?S_i"> is Bernoulli with probability <img src="https://latex.codecogs.com/png.latex?%5Cpi_i">,</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bgathered%7D%0A%5Coperatorname%7BVar%7D%5C!%5Cleft%5B%0AE(Y_i%5Cmid%20S_i,X_i,Z_i)%0A%5Cright%5D%20%5C%5C%0A=%5Cmu_i%5E2%5Coperatorname%7BVar%7D(1-S_i)%20%5C%5C%0A=%5Cpi_i(1-%5Cpi_i)%5Cmu_i%5E2.%0A%5Cend%7Bgathered%7D%0A"></p>
<p>Adding the within-state and between-state contributions gives the mixture variance:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Coperatorname%7BVar%7D(Y_i%5Cmid%20X_i,Z_i)%0A=%0A%5Cunderbrace%7B(1-%5Cpi_i)V_c(%5Cmu_i)%7D_%7B%5Ctext%7Bwithin-state%20variation%7D%7D%0A+%0A%5Cunderbrace%7B%5Cpi_i(1-%5Cpi_i)%5Cmu_i%5E2%7D_%7B%5Ctext%7Bbetween-state%20variation%7D%7D.%0A"></p>
</div>
</div>
</div>
<p>The count distribution determines <img src="https://latex.codecogs.com/png.latex?V_c(%5Cmu_i)">. A Poisson count state has <img src="https://latex.codecogs.com/png.latex?V_c(%5Cmu_i)=%5Cmu_i">, giving a <strong>zero-inflated Poisson (ZIP)</strong> model. An NB2 count state has <img src="https://latex.codecogs.com/png.latex?V_c(%5Cmu_i)=%5Cmu_i+%5Cmu_i%5E2/%5Cphi">, giving a <strong>zero-inflated negative-binomial (ZINB)</strong> model. The resulting mixture variances are shown below.</p>
<div id="tbl-zero-inflated-moments" class="responsive quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-zero-inflated-moments-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;6: Count-component probabilities and resulting mixture variances for ZIP and ZINB.
</figcaption>
<div aria-describedby="tbl-zero-inflated-moments-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="table-responsive">
<table class="caption-top table">
<colgroup>
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
<col style="width: 25%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">Model</th>
<th style="text-align: left;">Count-state zero probability <img src="https://latex.codecogs.com/png.latex?f_c(0)"></th>
<th style="text-align: left;">Count-state variance <img src="https://latex.codecogs.com/png.latex?V_c(%5Cmu_i)"></th>
<th style="text-align: left;">Conditional mixture variance</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">ZIP</td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?e%5E%7B-%5Cmu_i%7D"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%5Cmu_i"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?(1-%5Cpi_i)%5Cmu_i+%5Cpi_i(1-%5Cpi_i)%5Cmu_i%5E2"></td>
</tr>
<tr class="even">
<td style="text-align: left;">ZINB (NB2)</td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%5Cleft(%5Cdfrac%7B%5Cphi%7D%7B%5Cphi+%5Cmu_i%7D%5Cright)%5E%5Cphi"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%5Cmu_i+%5Cdfrac%7B%5Cmu_i%5E2%7D%7B%5Cphi%7D"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?(1-%5Cpi_i)%5Cleft(%5Cmu_i+%5Cdfrac%7B%5Cmu_i%5E2%7D%7B%5Cphi%7D%5Cright)+%5Cpi_i(1-%5Cpi_i)%5Cmu_i%5E2"></td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
<p>Both models have conditional mixture mean <img src="https://latex.codecogs.com/png.latex?(1-%5Cpi_i)%5Cmu_i">. Their difference lies in the spread around that mean. ZIP uses a Poisson count state, whereas ZINB adds the term <img src="https://latex.codecogs.com/png.latex?%5Cmu_i%5E2/%5Cphi"> and therefore allows overdispersion within the count-generating state. As <img src="https://latex.codecogs.com/png.latex?%5Cphi%5Cto%5Cinfty">, that additional variation disappears and the ZINB expressions approach their ZIP counterparts.</p>
<p>For the Medicare case study, the mean identity tells us how to calculate expected observed visits, while the variance distinguishes what each count distribution can represent. The next section connects <img src="https://latex.codecogs.com/png.latex?%5Cpi_i"> and <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> to predictors and asks how changes in either component affect the overall mean.</p>
</section>
<section id="regression-and-overall-effects" class="level2" data-number="4.4">
<h2 data-number="4.4" class="anchored" data-anchor-id="regression-and-overall-effects"><span class="header-section-number">4.4</span> Regression and Overall Effects</h2>
<p>We have seen that the overall mean depends on both the count-state mean <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> and the extra-zero probability <img src="https://latex.codecogs.com/png.latex?%5Cpi_i">. The next question is then: how does a predictor change that mean?</p>
<p>In a zero-inflated model, a predictor may change expected visits within the count-generating state, the probability of the extra-zero state, or both. Its component coefficient therefore need not describe its association with observed visits.</p>
<p>Let <img src="https://latex.codecogs.com/png.latex?X_i"> contain the count-component predictors and let <img src="https://latex.codecogs.com/png.latex?%5Cbeta"> contain their coefficients. Let <img src="https://latex.codecogs.com/png.latex?Z_i"> contain the zero-inflation predictors and let <img src="https://latex.codecogs.com/png.latex?%5Cgamma"> contain their coefficients. In <code>glmmTMB</code>, the zero-inflation component always uses a logit link. The count-component link is more flexible: the log link is the default for the Poisson and NB2 distributions used here, as it is for most count distributions available in <code>glmmTMB</code>, but it can be changed. The models in this tutorial therefore use</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A%5Clog(%5Cmu_i)%20&amp;=%20X_i%5Cbeta,%20%5C%5C%0A%5Coperatorname%7Blogit%7D(%5Cpi_i)%20&amp;=%20Z_i%5Cgamma.%0A%5Cend%7Baligned%7D%0A"></p>
<p>The log link keeps <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> positive, while the logit link keeps <img src="https://latex.codecogs.com/png.latex?%5Cpi_i"> between zero and one. A predictor may appear in either equation or in both.</p>
<p><strong>Count component</strong>: For a predictor <img src="https://latex.codecogs.com/png.latex?x_j"> in <img src="https://latex.codecogs.com/png.latex?X_i">, <img src="https://latex.codecogs.com/png.latex?e%5E%7B%5Cbeta_j%7D"> is the rate ratio for a one-unit increase in <img src="https://latex.codecogs.com/png.latex?x_j">, holding the other count-component predictors fixed. It describes how <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> changes within the count-generating state.</p>
<p><strong>Zero-inflation component</strong>: For a predictor <img src="https://latex.codecogs.com/png.latex?x_j"> in <img src="https://latex.codecogs.com/png.latex?Z_i">, <img src="https://latex.codecogs.com/png.latex?e%5E%7B%5Cgamma_j%7D"> is the odds ratio for the extra-zero state. A value above one means that a one-unit increase in <img src="https://latex.codecogs.com/png.latex?x_j"> raises the modelled odds of that state, holding the other zero-inflation predictors fixed.</p>
<p>Neither coefficient alone answers the practical question: how do expected observed visits change? That quantity still requires both components, which as we have seen in the previous section, is given by:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Am_i%0A=E(Y_i%5Cmid%20X_i,Z_i)%0A=(1-%5Cpi_i)%5Cmu_i.%0A"></p>
<p>In essence, the two pathways can reinforce or offset one another. Suppose a one-unit increase in a predictor raises <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> from 4 to 5 but also raises <img src="https://latex.codecogs.com/png.latex?%5Cpi_i"> from 0.10 to 0.30. The count-state mean increases by 25%, yet the overall mean falls slightly, from <img src="https://latex.codecogs.com/png.latex?(1-0.10)4=3.6"> to <img src="https://latex.codecogs.com/png.latex?(1-0.30)5=3.5">. The higher extra-zero probability more than offsets the higher count-state mean. If <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> rises while <img src="https://latex.codecogs.com/png.latex?%5Cpi_i"> falls, the two pathways instead reinforce one another.</p>
<div class="callout callout-style-default callout-caution callout-titled" title="Combining both pathways">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-7-contents" aria-controls="callout-7" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Caution</span>Combining both pathways
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-7" class="callout-7-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>For the additive linear predictors used here, suppose <img src="https://latex.codecogs.com/png.latex?x_j"> appears in both components. A one-unit increase gives the overall expected-count ratio</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7Bm_i(x_j+1)%7D%7Bm_i(x_j)%7D%0A=%0A%5Cunderbrace%7Be%5E%7B%5Cbeta_j%7D%7D_%7B%5Ctext%7Bcount-state%20change%7D%7D%0A%5Cunderbrace%7B%0A%5Cfrac%7B1-%5Cpi_i(x_j+1)%7D%7B1-%5Cpi_i(x_j)%7D%0A%7D_%7B%5Ctext%7Bcount-state%20probability%20change%7D%7D.%0A"></p>
<p>The first factor is the change in the count-state mean. The second is the change in the probability of being in the count-generating state. If <img src="https://latex.codecogs.com/png.latex?x_j"> appears only in the count component, the second factor equals one. If it appears only in the zero-inflation component, the first factor equals one.</p>
<p>Unlike the count-state factor <img src="https://latex.codecogs.com/png.latex?e%5E%7B%5Cbeta_j%7D">, the second factor depends on the starting value of <img src="https://latex.codecogs.com/png.latex?%5Cpi_i">. The combined ratio can therefore vary across patient profiles.</p>
</div>
</div>
</div>
<p>Because the pathways can reinforce or offset one another, component coefficient tables do not show how expected observed visits change. Section 5 therefore uses response-scale predictions of <img src="https://latex.codecogs.com/png.latex?m_i"> rather than stopping at rate ratios and odds ratios. Before fitting those models, however, we must decide which predictors belong in each component.</p>
</section>
<section id="choosing-predictors" class="level2" data-number="4.5">
<h2 data-number="4.5" class="anchored" data-anchor-id="choosing-predictors"><span class="header-section-number">4.5</span> Choosing Predictors</h2>
<p>As we have seen in the previous section, placing a variable in one formula but not the other restricts which part of the outcome distribution it may change, and as such is an important choice to make.</p>
<p>The two components pose different questions:</p>
<ol type="1">
<li>Which variables describe visit intensity within the count-generating state?</li>
<li>Which variables plausibly describe the probability of the extra-zero state?</li>
</ol>
<p>The count component retains the baseline adjustment set used in the Poisson analysis:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1">ofp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> healthpoor <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> healthexcellent <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> numchron <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> age <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> male <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> married</span></code></pre></div></div>
<p>These predictors represent health need and demographic differences that may be associated with visit rates. Their inclusion defines the conditional comparison; it does not turn the resulting coefficients into causal effects.</p>
<p>Two available variables are deliberately left out. <code>hosp</code> counts hospital stays during the same observation period as the office visits, so treating it as a prior predictor would blur the temporal ordering between two concurrent measures of healthcare use. <code>school</code> records years of education and could reasonably enter as a socioeconomic covariate. We leave it out to keep the teaching specification focused. The count formula is a starting point, and a fuller analysis would compare other substantively plausible alternatives.</p>
<p>Ideally, the zero-inflation formula would include direct measures of why someone cannot or does not enter the visit-generating process, such as eligibility restrictions, insurance coverage, or geographic access. The <code>medcare</code> data unfortunately contain no such measures. Its health and demographic variables can describe systematic differences in the estimated extra-zero probability, but they cannot identify the mechanism behind those differences.</p>
<p>For the initial ZIP and ZINB comparison, the zero-inflation component uses the more compact formula:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> numchron <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> male <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> married</span></code></pre></div></div>
<p>Chronic conditions, sex, and marital status showed the clearest adjusted associations with an <strong>observed zero</strong> in Table&nbsp;2. That result provides an empirical starting point, but it’s not a direct measurement of extra-zero membership: as established in the mixture-probability subsection, observed zeros combine both possible routes to zero.</p>
<p>These three predictors therefore enter both components initially, allowing each to be associated with visit intensity and with the estimated extra-zero probability. Including or excluding a predictor imposes a substantive restriction, and the available variables provide only indirect support for either choice. In the next section we will therefore also compare some alternative zero-inflation specifications.</p>
</section>
</section>
<section id="fitting-checking-and-interpreting-the-models" class="level1" data-number="5">
<h1 data-number="5"><span class="header-section-number">5</span> Fitting, Checking, and Interpreting the Models</h1>
<p>The predictor-selection discussion showed that predictor placement changes what a zero-inflated model represents: the count formula governs <img src="https://latex.codecogs.com/png.latex?%5Cmu_i">, while the zero formula governs <img src="https://latex.codecogs.com/png.latex?%5Cpi_i">. Model comparison must therefore distinguish the count distribution from the presence and specification of the extra-zero component. We will address three decisions in order:</p>
<ol type="1">
<li><strong>Does the count component require NB2 rather than Poisson variation?</strong></li>
<li><strong>After allowing NB2 variation, does the model benefit from any extra-zero component?</strong></li>
<li><strong>If it does, should the extra-zero probability be constant or vary with patient characteristics?</strong></li>
</ol>
<p>Each question requires a matched contrast. Poisson and NB2 use the same count formula and no zero component. Ordinary NB2 and intercept-only ZINB use the same count formula and count family; <code>ziformula = ~ 1</code> adds one constant extra-zero probability rather than allowing it to vary across records. The intercept-only and covariate-dependent ZINBs then hold the NB2 count process fixed while changing only the zero formula.</p>
<p>ZIP remains useful for a different contrast. Comparing ZIP with the compact ZINB holds both formulas fixed and asks whether the count component still needs NB2 variation inside a zero-inflated model. ZIP can therefore show why adding an extra-zero component does not repair an inadequate Poisson count distribution. Comparing ZIP directly with ordinary NB2 would change both the count family and the zero formula, so it would not isolate evidence for an extra-zero component.</p>
<section id="fit-matched-candidate-specifications" class="level2" data-number="5.1">
<h2 data-number="5.1" class="anchored" data-anchor-id="fit-matched-candidate-specifications"><span class="header-section-number">5.1</span> Fit Matched Candidate Specifications</h2>
<p>For the sake of simplicity and exposition, every specification considered here uses the same count formula:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1">ofp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> healthpoor <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> healthexcellent <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> numchron <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> age <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> male <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> married</span></code></pre></div></div>
<p>The Poisson baseline uses the Poisson family with no zero component, while the negative-binomial baseline uses NB2 with no zero component. This subsection adds only the candidates needed for the first comparisons:</p>
<ul>
<li><strong>Compact ZIP:</strong> Poisson count family with <code>~ numchron + male + married</code> as its zero formula.</li>
<li><strong>Intercept-only ZINB:</strong> NB2 count family with <code>~ 1</code> as its zero formula.</li>
<li><strong>Compact ZINB:</strong> NB2 count family with <code>~ numchron + male + married</code> as its zero formula.</li>
</ul>
<p>Additional zero-component formulas are deferred until their rationale is introduced.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-14" data-llms-code-original="compact_zi_formula <- ~ numchron + male + married # <1>

# Compact zero-inflated Poisson model
zip_model <- glmmTMB(
  count_formula,
  ziformula = compact_zi_formula, # <2>
  data = medcare,
  family = poisson()
)

# Intercept-only zero-inflated NB2 model
zinb_intercept_model <- glmmTMB(
  count_formula,
  ziformula = ~ 1, # <3>
  data = medcare,
  family = nbinom2()
)

zinb_compact_model <- glmmTMB(
  count_formula,
  ziformula = compact_zi_formula, 
  data = medcare,
  family = nbinom2() # <4>
)" style="background: #f1f3f5;"><pre class="sourceCode r code-annotation-code code-with-copy code-annotated"><code class="sourceCode r"><a class="code-annotation-anchor" data-target-cell="annotated-cell-14" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-14-1" class="code-annotation-target">compact_zi_formula <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">~</span> numchron <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> male <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> married</span>
<span id="annotated-cell-14-2"></span>
<span id="annotated-cell-14-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compact zero-inflated Poisson model</span></span>
<span id="annotated-cell-14-4">zip_model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmmTMB</span>(</span>
<span id="annotated-cell-14-5">  count_formula,</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-14" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-14-6" class="code-annotation-target">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ziformula =</span> compact_zi_formula,</span>
<span id="annotated-cell-14-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> medcare,</span>
<span id="annotated-cell-14-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">poisson</span>()</span>
<span id="annotated-cell-14-9">)</span>
<span id="annotated-cell-14-10"></span>
<span id="annotated-cell-14-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Intercept-only zero-inflated NB2 model</span></span>
<span id="annotated-cell-14-12">zinb_intercept_model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmmTMB</span>(</span>
<span id="annotated-cell-14-13">  count_formula,</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-14" data-target-annotation="3" onclick="event.preventDefault();">3</a><span id="annotated-cell-14-14" class="code-annotation-target">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ziformula =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="annotated-cell-14-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> medcare,</span>
<span id="annotated-cell-14-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nbinom2</span>()</span>
<span id="annotated-cell-14-17">)</span>
<span id="annotated-cell-14-18"></span>
<span id="annotated-cell-14-19">zinb_compact_model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmmTMB</span>(</span>
<span id="annotated-cell-14-20">  count_formula,</span>
<span id="annotated-cell-14-21">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ziformula =</span> compact_zi_formula, </span>
<span id="annotated-cell-14-22">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> medcare,</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-14" data-target-annotation="4" onclick="event.preventDefault();">4</a><span id="annotated-cell-14-23" class="code-annotation-target">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nbinom2</span>()</span>
<span id="annotated-cell-14-24">)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-14" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-14" data-code-lines="1" data-code-annotation="1">The compact zero formula carries forward the clearest adjusted associations with observed zeros from Table&nbsp;2.</span>
</dd>
<dt data-target-cell="annotated-cell-14" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-14" data-code-lines="6" data-code-annotation="2">Compact ZIP and compact ZINB use the same count and zero formulas, so their contrast changes only the count distribution.</span>
</dd>
<dt data-target-cell="annotated-cell-14" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-14" data-code-lines="14" data-code-annotation="3">With <code>nbinom2()</code>, <code>ziformula = ~ 1</code> assigns every record the same fitted probability of the latent extra-zero state. The NB2 count mean can still vary with the predictors in <code>count_formula</code>.</span>
</dd>
<dt data-target-cell="annotated-cell-14" data-target-annotation="4">4</dt>
<dd>
<span data-code-cell="annotated-cell-14" data-code-lines="23" data-code-annotation="4">Pairing a covariate-dependent <code>ziformula</code> with <code>nbinom2()</code> lets the extra-zero probability vary across patient characteristics while retaining NB2 variation in the count process.</span>
</dd>
</dl>
</div>
</div>
<p>We compare these specifications in matched pairs because each pair isolates one modelling decision: the count family, the addition of a constant extra-zero probability, or whether that probability varies with patient characteristics.</p>
<p>It’s important to keep in mind that the resulting fit statistics provide relative evidence among the specifications, but they neither identify a distinct extra-zero population nor replace distributional diagnostics, which are still needed to assess whether the chosen count distribution adequately represents the data.</p>
</section>
<section id="separate-count-family-and-zero-component-evidence" class="level2" data-number="5.2">
<h2 data-number="5.2" class="anchored" data-anchor-id="separate-count-family-and-zero-component-evidence"><span class="header-section-number">5.2</span> Separate Count-Family and Zero-Component Evidence</h2>
<p>The fitted specifications now let us separate the three decisions posed at the start of this section. We first compare Poisson with NB2, using both the ordinary and zero-inflated versions, to choose the count family. We then return to the ordinary NB2 baseline and add the simplest possible extra-zero component before asking whether that component should vary across patient characteristics.</p>
<p>Both <a href="https://en.wikipedia.org/wiki/Akaike_information_criterion">AIC</a> and <a href="https://en.wikipedia.org/wiki/Bayesian_information_criterion">BIC</a> ask whether an improvement in likelihood is worth the additional parameters. Lower values favour a specification, but only differences among models fitted to the same observations with compatible likelihoods are meaningful. AIC emphasises expected predictive accuracy, whereas BIC is more reluctant to add parameters at this sample size, so comparing them shows how sensitive the result is to the penalty for complexity. These scores can rank the candidates considered here; the residual checks later will show whether the leading models are actually able to reproduce the data.</p>
<p>How large do these differences need to be? There is no universal pass-or-fail cutoff. Values that are close together indicate little separation between two specifications, whereas gaps of hundreds or thousands show a clear preference for the model with the lower value.</p>
<div class="cell">
<details class="code-fold">
<summary>Show model-comparison code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb17-1">models <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb17-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Poisson =</span> poisson_model,</span>
<span id="cb17-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">NB2 =</span> nb_model,</span>
<span id="cb17-4">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Compact ZIP</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> zip_model,</span>
<span id="cb17-5">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Intercept-only ZINB</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> zinb_intercept_model,</span>
<span id="cb17-6">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Compact ZINB</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> zinb_compact_model</span>
<span id="cb17-7">)</span>
<span id="cb17-8"></span>
<span id="cb17-9">comparison_table <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb17-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Model =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(models),</span>
<span id="cb17-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">AIC =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(models, AIC, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)),</span>
<span id="cb17-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">BIC =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(models, BIC, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)),</span>
<span id="cb17-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">RMSE =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(</span>
<span id="cb17-14">    models,</span>
<span id="cb17-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(model) {</span>
<span id="cb17-16">      predictions <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predict</span>(model, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"response"</span>)</span>
<span id="cb17-17">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>((medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ofp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> predictions)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb17-18">    },</span>
<span id="cb17-19">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb17-20">  )</span>
<span id="cb17-21">) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb17-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(</span>
<span id="cb17-23">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">across</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(AIC, BIC), <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(.x, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)),</span>
<span id="cb17-24">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">RMSE =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(RMSE, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb17-25">  )</span>
<span id="cb17-26"></span>
<span id="cb17-27">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(comparison_table, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>))</span></code></pre></div></div>
</details>
<div id="tbl-model-performance" class="cell quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-model-performance-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;7: In-sample comparison of five candidate model specifications. Lower AIC, BIC, and RMSE values indicate better fit by each criterion.
</figcaption>
<div aria-describedby="tbl-model-performance-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output-display">
<table class="cell caption-top table table-sm table-striped small">
<thead>
<tr class="header">
<th style="text-align: left;">Model</th>
<th style="text-align: right;">AIC</th>
<th style="text-align: right;">BIC</th>
<th style="text-align: right;">RMSE</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Poisson</td>
<td style="text-align: right;">37093.4</td>
<td style="text-align: right;">37138.1</td>
<td style="text-align: right;">6.505</td>
</tr>
<tr class="even">
<td style="text-align: left;">NB2</td>
<td style="text-align: right;">24576.1</td>
<td style="text-align: right;">24627.2</td>
<td style="text-align: right;">6.529</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Compact ZIP</td>
<td style="text-align: right;">33115.3</td>
<td style="text-align: right;">33185.6</td>
<td style="text-align: right;">6.488</td>
</tr>
<tr class="even">
<td style="text-align: left;">Intercept-only ZINB</td>
<td style="text-align: right;">24574.4</td>
<td style="text-align: right;">24631.9</td>
<td style="text-align: right;">6.525</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Compact ZINB</td>
<td style="text-align: right;">24458.0</td>
<td style="text-align: right;">24534.7</td>
<td style="text-align: right;">6.496</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</div>
<p>We start with the count family. Moving from Poisson to NB2 lowers AIC from 37093.4 to 24576.1 when neither model has an extra-zero component. Holding the compact zero formula fixed leads to the same conclusion: moving from ZIP to compact ZINB lowers AIC from 33115.3 to 24458.0. BIC tells the same story in both comparisons. These gaps leave little doubt that Poisson variation is too restrictive here, whether or not the model includes an extra-zero component.</p>
<p>The next question is whether NB2 needs an extra-zero component at all. The cleanest starting point is intercept-only ZINB: it keeps the NB2 count process unchanged and assigns every participant the same extra-zero probability. Compared with ordinary NB2, its AIC is only 1.7 points lower, while its BIC is 4.7 points higher. The small AIC gap and the reversal under BIC suggest that a constant extra-zero probability adds little to the ordinary NB2 model.</p>
<p>What changes when the extra-zero probability can vary between participants? Relative to intercept-only ZINB, the compact ZINB lowers AIC by 116.4 points and BIC by 97.2 points. Both gaps are large: allowing the zero component to vary with chronic conditions, sex, and marital status improves the fitted distribution substantially. It does not, however, show that the zeros came from a separate, identifiable group of patients.</p>
<p>The RMSE column appears to disagree with AIC and BIC because it assesses only the predicted average. For each participant, RMSE compares the observed count with the model’s expected count; it does not consider how much probability the model assigned to that count or to other possible counts. Compact ZIP therefore achieves the lowest RMSE, 6.488, even though its AIC and BIC are much higher than those of the NB2 models. Two models can predict similar averages while assigning very different probabilities to zeros, moderate counts, and unusually high counts. If prediction became a primary goal, repeated cross-validation should assess a score for the entire predictive distribution, such as held-out log predictive density or ranked probability score, alongside RMSE.</p>
<p>The comparison therefore narrows the next decision: retain NB2 variation in the count component, then ask which covariate-dependent zero formula, if any, provides a defensible working specification.</p>
</section>
<section id="choose-the-zero-component-specification" class="level2" data-number="5.3">
<h2 data-number="5.3" class="anchored" data-anchor-id="choose-the-zero-component-specification"><span class="header-section-number">5.3</span> Choose the Zero-Component Specification</h2>
<p>The preceding comparison showed that adding a constant extra-zero probability to NB2 changes fit very little, whereas allowing that probability to vary across participants produces a much larger improvement. That result leaves an important specification question: which participant characteristics should be allowed to change the extra-zero probability?</p>
<p>Starting from the intercept-only ZINB, we compare three ways of allowing that probability to vary:</p>
<ul>
<li>The excellent-health specification represents a narrow health-need explanation;</li>
<li>The compact specification carries forward the strongest adjusted associations with an observed zero in these data;</li>
<li>The shared-adjustment specification allows every count predictor to have a separate zero-component association.</li>
</ul>
<p>All four models retain the same NB2 count family and count formula, so the comparison concerns only the zero-component specification. This small candidate set tests whether the compact model’s improvement depends on its particular formula and whether the broader specification earns its additional complexity.</p>
<div class="cell">
<details class="code-fold">
<summary>Show ZINB specification-comparison code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1">zinb_spec_models <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb18-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Intercept-only</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> zinb_intercept_model,</span>
<span id="cb18-3">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Excellent-health only</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmmTMB</span>(</span>
<span id="cb18-4">    count_formula,</span>
<span id="cb18-5">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ziformula =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> healthexcellent,</span>
<span id="cb18-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> medcare,</span>
<span id="cb18-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nbinom2</span>()</span>
<span id="cb18-8">  ),</span>
<span id="cb18-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Compact =</span> zinb_compact_model,</span>
<span id="cb18-10">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Shared adjustment set</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glmmTMB</span>(</span>
<span id="cb18-11">    count_formula,</span>
<span id="cb18-12">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ziformula =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> healthpoor <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> healthexcellent <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> numchron <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb18-13">      age <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> male <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> married,</span>
<span id="cb18-14">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> medcare,</span>
<span id="cb18-15">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">family =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nbinom2</span>()</span>
<span id="cb18-16">  )</span>
<span id="cb18-17">)</span>
<span id="cb18-18"></span>
<span id="cb18-19">zinb_model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> zinb_spec_models[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Compact"</span>]]</span>
<span id="cb18-20"></span>
<span id="cb18-21">zinb_spec_table <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb18-22">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Specification =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(zinb_spec_models),</span>
<span id="cb18-23">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Zero-inflation formula</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb18-24">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ 1"</span>,</span>
<span id="cb18-25">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ healthexcellent"</span>,</span>
<span id="cb18-26">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sub</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"^~"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ "</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(compact_zi_formula)),</span>
<span id="cb18-27">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"~ healthpoor + healthexcellent + numchron + age + male + married"</span></span>
<span id="cb18-28">  ),</span>
<span id="cb18-29">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Substantive restriction</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb18-30">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Keeps the extra-zero probability constant across participants."</span>,</span>
<span id="cb18-31">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Allows an excellent-health difference, but none by the other predictors; average and poor health share the same fitted probability."</span>,</span>
<span id="cb18-32">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Allows differences by chronic-condition count, sex, and marital status; excludes age and additional self-rated-health differences."</span>,</span>
<span id="cb18-33">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Allows each count predictor its own zero-component association; imposes the fewest restrictions at the cost of three additional coefficients."</span></span>
<span id="cb18-34">  ),</span>
<span id="cb18-35">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">AIC =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(zinb_spec_models, AIC, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)),</span>
<span id="cb18-36">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">BIC =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(zinb_spec_models, BIC, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span>
<span id="cb18-37">) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb18-38">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(</span>
<span id="cb18-39">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">across</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(AIC, BIC), <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(.x, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span>
<span id="cb18-40">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb18-41">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">arrange</span>(AIC)</span>
<span id="cb18-42"></span>
<span id="cb18-43">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(zinb_spec_table, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>))</span></code></pre></div></div>
</details>
<div id="tbl-zinb-specification-candidates" class="cell quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-zinb-specification-candidates-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;8: Comparison of four candidate ZINB zero-component specifications. Every model uses the same NB2 count family and count formula.
</figcaption>
<div aria-describedby="tbl-zinb-specification-candidates-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output-display">
<table class="cell caption-top table table-sm table-striped small">
<colgroup>
<col style="width: 8%">
<col style="width: 26%">
<col style="width: 57%">
<col style="width: 3%">
<col style="width: 3%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">Specification</th>
<th style="text-align: left;">Zero-inflation formula</th>
<th style="text-align: left;">Substantive restriction</th>
<th style="text-align: right;">AIC</th>
<th style="text-align: right;">BIC</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Shared adjustment set</td>
<td style="text-align: left;">~ healthpoor + healthexcellent + numchron + age + male + married</td>
<td style="text-align: left;">Allows each count predictor its own zero-component association; imposes the fewest restrictions at the cost of three additional coefficients.</td>
<td style="text-align: right;">24457.8</td>
<td style="text-align: right;">24553.6</td>
</tr>
<tr class="even">
<td style="text-align: left;">Compact</td>
<td style="text-align: left;">~ numchron + male + married</td>
<td style="text-align: left;">Allows differences by chronic-condition count, sex, and marital status; excludes age and additional self-rated-health differences.</td>
<td style="text-align: right;">24458.0</td>
<td style="text-align: right;">24534.7</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Intercept-only</td>
<td style="text-align: left;">~ 1</td>
<td style="text-align: left;">Keeps the extra-zero probability constant across participants.</td>
<td style="text-align: right;">24574.4</td>
<td style="text-align: right;">24631.9</td>
</tr>
<tr class="even">
<td style="text-align: left;">Excellent-health only</td>
<td style="text-align: left;">~ healthexcellent</td>
<td style="text-align: left;">Allows an excellent-health difference, but none by the other predictors; average and poor health share the same fitted probability.</td>
<td style="text-align: right;">24576.0</td>
<td style="text-align: right;">24639.9</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</div>
<p>The four zero formulas are not all nested, so no single likelihood-ratio test can compare all of them. We therefore use the information-criterion framework introduced above: AIC for relative in-sample comparison and BIC as a stronger parsimony check.</p>
<p>The results give us little reason to carry forward the intercept-only or excellent-health-only models. As the preceding comparison showed, the intercept-only model receives little support beyond ordinary NB2. Allowing the extra-zero probability to vary only with excellent health does no better: its AIC is 24576.0 and its BIC is 24639.9, both higher than the intercept-only model’s values of 24574.4 and 24631.9. A single excellent-health indicator is therefore too narrow to reproduce the improvement seen with the compact formula.</p>
<p>That leaves the compact and shared-adjustment specifications. The shared-adjustment model lowers AIC by only 0.2 points, from 24458.0 to 24457.8, but raises BIC by 18.9 points. I therefore keep the compact formula: the three extra coefficients in the shared-adjustment model make almost no difference to AIC and incur a much larger BIC penalty.</p>
<p>The compact formula was chosen partly after examining adjusted associations with an observed zero in this same dataset, and remains a provisional teaching specification.</p>
<p>Given the results, for the rest of the article, we carry forward <code>~ numchron + male + married</code> as the <strong>provisional compact ZINB working specification</strong>. The confidence intervals and p-values reported later treat this formula as if it had been fixed before the analysis. They do not account for the predictor-selection step.</p>
<p>Finally, before relying on these comparisons, it’s good practice to check whether each candidate produced a numerically trustworthy solution. A successful optimizer termination, a positive-definite Hessian, and finite standard errors indicate that the software found a well-defined optimum. Large zero-component coefficients can instead signal a nearly flat likelihood in which the extra-zero probability approaches zero or one.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-8-contents" aria-controls="callout-8" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Checking for estimation stability
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-8" class="callout-8-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>The code below applies the same checks to every <code>glmmTMB</code> candidate used in the information-criterion comparisons. It then reports the number of flagged candidates and shows the compact ZINB as a worked example. The supplementary <code>diagnose()</code> call checks coefficient magnitudes, predictor scaling, and Hessian curvature. We disable its large-<img src="https://latex.codecogs.com/png.latex?z"> screen because a precisely estimated association is not by itself an optimization failure.</p>
<div class="cell">
<details class="code-fold">
<summary>Show estimation-stability checks for the fitted candidates.</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb19-1">candidate_glmmtmb_models <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb19-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb19-3">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">NB2 =</span> nb_model,</span>
<span id="cb19-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Compact ZIP</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> zip_model</span>
<span id="cb19-5">  ),</span>
<span id="cb19-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">setNames</span>(</span>
<span id="cb19-7">    zinb_spec_models,</span>
<span id="cb19-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(zinb_spec_models), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ZINB"</span>)</span>
<span id="cb19-9">  )</span>
<span id="cb19-10">)</span>
<span id="cb19-11"></span>
<span id="cb19-12">check_estimation_stability <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(model) {</span>
<span id="cb19-13">  coefficient_blocks <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(model)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>coefficients</span>
<span id="cb19-14">  standard_errors <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unlist</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(</span>
<span id="cb19-15">    coefficient_blocks,</span>
<span id="cb19-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(block) {</span>
<span id="cb19-17">      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.null</span>(block) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">||</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(block) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) {</span>
<span id="cb19-18">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>))</span>
<span id="cb19-19">      }</span>
<span id="cb19-20">      block[, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Std. Error"</span>]</span>
<span id="cb19-21">    }</span>
<span id="cb19-22">  ))</span>
<span id="cb19-23">  zero_coefficients <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unname</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fixef</span>(model)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>zi)</span>
<span id="cb19-24"></span>
<span id="cb19-25">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># diagnose() prints a short message, so capture it while retaining its result.</span></span>
<span id="cb19-26">  diagnose_message <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">capture.output</span>(</span>
<span id="cb19-27">    diagnose_ok <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> glmmTMB<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diagnose</span>(</span>
<span id="cb19-28">      model,</span>
<span id="cb19-29">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">check_zstats =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb19-30">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">explain =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb19-31">    )</span>
<span id="cb19-32">  )</span>
<span id="cb19-33"></span>
<span id="cb19-34">  tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb19-35">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">optimizer_ok =</span> model<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fit<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>convergence <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb19-36">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hessian_ok =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isTRUE</span>(model<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sdr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pdHess),</span>
<span id="cb19-37">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">finite_se =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(standard_errors) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span></span>
<span id="cb19-38">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.finite</span>(standard_errors)),</span>
<span id="cb19-39">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">extreme_zero_coefficient =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(zero_coefficients) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span></span>
<span id="cb19-40">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">any</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(zero_coefficients) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>),</span>
<span id="cb19-41">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">diagnose_ok =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isTRUE</span>(diagnose_ok)</span>
<span id="cb19-42">  )</span>
<span id="cb19-43">}</span>
<span id="cb19-44"></span>
<span id="cb19-45">stability_checks <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> dplyr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bind_rows</span>(</span>
<span id="cb19-46">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(candidate_glmmtmb_models, check_estimation_stability),</span>
<span id="cb19-47">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.id =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Model"</span></span>
<span id="cb19-48">) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb19-49">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(</span>
<span id="cb19-50">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">all_checks_pass =</span> optimizer_ok <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> hessian_ok <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> finite_se <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span></span>
<span id="cb19-51">      <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>extreme_zero_coefficient <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> diagnose_ok</span>
<span id="cb19-52">  )</span>
<span id="cb19-53"></span>
<span id="cb19-54">compact_checks <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> stability_checks <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb19-55">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(Model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Compact ZINB"</span>)</span>
<span id="cb19-56"></span>
<span id="cb19-57">stability_status <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bind_rows</span>(</span>
<span id="cb19-58">  tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb19-59">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Scope =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"All comparison candidates"</span>,</span>
<span id="cb19-60">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Check =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Candidates with one or more flagged checks"</span>,</span>
<span id="cb19-61">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Result =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(</span>
<span id="cb19-62">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%d of %d"</span>,</span>
<span id="cb19-63">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>stability_checks<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>all_checks_pass),</span>
<span id="cb19-64">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(stability_checks)</span>
<span id="cb19-65">    )</span>
<span id="cb19-66">  ),</span>
<span id="cb19-67">  tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb19-68">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Scope =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Compact ZINB"</span>,</span>
<span id="cb19-69">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Check =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb19-70">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Optimizer termination"</span>,</span>
<span id="cb19-71">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Positive-definite Hessian"</span>,</span>
<span id="cb19-72">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Finite standard errors"</span>,</span>
<span id="cb19-73">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Zero-component coefficient magnitude"</span>,</span>
<span id="cb19-74">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Supplementary diagnose() checks"</span></span>
<span id="cb19-75">    ),</span>
<span id="cb19-76">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Result =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb19-77">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(compact_checks<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>optimizer_ok, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Passed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Flagged"</span>),</span>
<span id="cb19-78">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(compact_checks<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>hessian_ok, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Passed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Flagged"</span>),</span>
<span id="cb19-79">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(compact_checks<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>finite_se, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Passed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Flagged"</span>),</span>
<span id="cb19-80">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(</span>
<span id="cb19-81">        compact_checks<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>extreme_zero_coefficient,</span>
<span id="cb19-82">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Flagged"</span>,</span>
<span id="cb19-83">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"No coefficient with |estimate| &gt; 10"</span></span>
<span id="cb19-84">      ),</span>
<span id="cb19-85">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(compact_checks<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>diagnose_ok, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Passed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Flagged"</span>)</span>
<span id="cb19-86">    )</span>
<span id="cb19-87">  )</span>
<span id="cb19-88">)</span>
<span id="cb19-89"></span>
<span id="cb19-90">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(stability_status, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>))</span></code></pre></div></div>
</details>
<div id="tbl-estimation-stability" class="cell quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-estimation-stability-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;9: Estimation-stability checks for the fitted candidates, with detailed results for the compact ZINB working specification.
</figcaption>
<div aria-describedby="tbl-estimation-stability-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output-display">
<table class="cell caption-top table table-sm table-striped small">
<colgroup>
<col style="width: 22%">
<col style="width: 37%">
<col style="width: 40%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">Scope</th>
<th style="text-align: left;">Check</th>
<th style="text-align: left;">Result</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">All comparison candidates</td>
<td style="text-align: left;">Candidates with one or more flagged checks</td>
<td style="text-align: left;">0 of 6</td>
</tr>
<tr class="even">
<td style="text-align: left;">Compact ZINB</td>
<td style="text-align: left;">Optimizer termination</td>
<td style="text-align: left;">Passed</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Compact ZINB</td>
<td style="text-align: left;">Positive-definite Hessian</td>
<td style="text-align: left;">Passed</td>
</tr>
<tr class="even">
<td style="text-align: left;">Compact ZINB</td>
<td style="text-align: left;">Finite standard errors</td>
<td style="text-align: left;">Passed</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Compact ZINB</td>
<td style="text-align: left;">Zero-component coefficient magnitude</td>
<td style="text-align: left;">No coefficient with |estimate| &gt; 10</td>
</tr>
<tr class="even">
<td style="text-align: left;">Compact ZINB</td>
<td style="text-align: left;">Supplementary diagnose() checks</td>
<td style="text-align: left;">Passed</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</div>
<p><code>diagnose()</code> is an experimental troubleshooting aid, so the explicit optimizer, Hessian, standard-error, and coefficient checks remain visible rather than being replaced by one package-generated verdict.</p>
</div>
</div>
</div>
<p>All six <code>glmmTMB</code> candidates passed these checks, including the compact ZINB shown above. Their likelihood comparisons and coefficient estimates therefore show no evident numerical warning.</p>
</section>
<section id="check-distributional-fit" class="level2" data-number="5.4">
<h2 data-number="5.4" class="anchored" data-anchor-id="check-distributional-fit"><span class="header-section-number">5.4</span> Check Distributional Fit</h2>
<p>We now examine how closely the compact ZINB reproduces the observed visit counts. <code>DHARMa</code> simulates outcomes from the fitted model and compares each observation with its simulated distribution. It expresses the result as a scaled residual between 0 and 1; a well-calibrated model should produce residuals that are approximately uniform across that interval.</p>
<div class="callout callout-style-default callout-caution callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-9-contents" aria-controls="callout-9" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Caution</span>DHARMa’s scaled residuals
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-9" class="callout-9-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>For participant <img src="https://latex.codecogs.com/png.latex?i">, let <img src="https://latex.codecogs.com/png.latex?y_i"> be the observed count and let <img src="https://latex.codecogs.com/png.latex?y_i%5E%7B(1)%7D,%20%5Cldots,%20y_i%5E%7B(S)%7D"> denote <img src="https://latex.codecogs.com/png.latex?S"> responses simulated from the conditional fitted distribution implied by the model. In this tutorial, that distribution is determined by the participant’s covariates and the estimated ZINB parameters.</p>
<p>DHARMa approximates the fitted cumulative distribution function at the observation by calculating the proportions of simulated responses strictly below and less than or equal to the observed value:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AL_i%20=%20%5Cfrac%7B1%7D%7BS%7D%5Csum_%7Bs=1%7D%5E%7BS%7D%5Cmathbb%7B1%7D%5C!%5Cleft(y_i%5E%7B(s)%7D%20%3C%20y_i%5Cright),%0A%5Cqquad%0AU_i%20=%20%5Cfrac%7B1%7D%7BS%7D%5Csum_%7Bs=1%7D%5E%7BS%7D%5Cmathbb%7B1%7D%5C!%5Cleft(y_i%5E%7B(s)%7D%20%5Cleq%20y_i%5Cright).%0A"></p>
<p>Here, <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7B1%7D(A)"> is the indicator function: it equals 1 when statement <img src="https://latex.codecogs.com/png.latex?A"> is true and 0 otherwise. <img src="https://latex.codecogs.com/png.latex?L_i"> is the empirical cumulative distribution immediately to the left of <img src="https://latex.codecogs.com/png.latex?y_i">, while <img src="https://latex.codecogs.com/png.latex?U_i"> is its value at <img src="https://latex.codecogs.com/png.latex?y_i">. The interval from <img src="https://latex.codecogs.com/png.latex?L_i"> to <img src="https://latex.codecogs.com/png.latex?U_i"> therefore represents the fitted probability assigned to the observed count.</p>
<p>DHARMa then draws</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Ar_i%20%5Csim%20%5Coperatorname%7BUniform%7D(L_i,%20U_i).%0A"></p>
<p>Randomisation spreads observations tied at the same discrete count across the probability interval associated with that count. Under a correctly specified model and the conditional-independence assumption used here, these randomised residuals are approximately independent <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7BUniform%7D(0,1)"> variables; the approximation reflects the finite number of simulations. The <a href="https://stat.ethz.ch/CRAN/web/packages/DHARMa/vignettes/DHARMa.html">DHARMa vignette</a> develops the method and its diagnostic interpretation in more detail.</p>
</div>
</div>
</div>
<p>Three standard checks provide the first overview:</p>
<ol type="1">
<li><strong>Zero frequency:</strong> Does the model reproduce the number of observed zeros?</li>
<li><strong>Dispersion:</strong> Is the observed residual spread consistent with the simulations?</li>
<li><strong>Overall uniformity:</strong> Does the fitted conditional distribution reproduce the response more broadly?</li>
</ol>
<p>We begin with zero frequency because it was the specific weakness of the negative-binomial model. NB remains as a benchmark for that comparison; the other diagnostics show what changes when the compact ZINB repairs the zero count. I use 1,000 simulations, rather than DHARMa’s default of 250, to reduce Monte Carlo variation and support the bootstrap outlier check below. A fixed seed makes the results reproducible, and the same simulations supply every diagnostic and figure in this subsection.</p>
<div class="cell">
<details class="code-fold">
<summary>Show residual-simulation code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb20-1">nb_residuals <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulateResiduals</span>(</span>
<span id="cb20-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fittedModel =</span> nb_model,</span>
<span id="cb20-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>,</span>
<span id="cb20-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">seed =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">123</span>,</span>
<span id="cb20-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb20-6">)</span>
<span id="cb20-7"></span>
<span id="cb20-8">zinb_residuals <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">simulateResiduals</span>(</span>
<span id="cb20-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fittedModel =</span> zinb_model,</span>
<span id="cb20-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>,</span>
<span id="cb20-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">seed =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">123</span>,</span>
<span id="cb20-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb20-13">)</span></code></pre></div></div>
</details>
</div>
<div class="cell">
<details class="code-fold">
<summary>Show diagnostic-test code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb21-1">nb_zero_test <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">testZeroInflation</span>(nb_residuals, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb21-2">nb_dispersion_test <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">testDispersion</span>(nb_residuals, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb21-3">nb_uniformity_test <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">testUniformity</span>(nb_residuals, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb21-4"></span>
<span id="cb21-5">zinb_zero_test <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">testZeroInflation</span>(zinb_residuals, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb21-6">zinb_dispersion_test <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">testDispersion</span>(zinb_residuals, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb21-7">zinb_uniformity_test <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">testUniformity</span>(zinb_residuals, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb21-8"></span>
<span id="cb21-9">format_diagnostic <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(statistic, p_value, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) {</span>
<span id="cb21-10">  p_text <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(p_value, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">eps =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>)</span>
<span id="cb21-11">  p_text <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">startsWith</span>(p_text, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;"</span>)) {</span>
<span id="cb21-12">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sub</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt; "</span>, p_text, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fixed =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb21-13">  } <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> {</span>
<span id="cb21-14">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"="</span>, p_text)</span>
<span id="cb21-15">  }</span>
<span id="cb21-16"></span>
<span id="cb21-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%."</span>, digits, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f (p %s)"</span>), statistic, p_text)</span>
<span id="cb21-18">}</span>
<span id="cb21-19"></span>
<span id="cb21-20">diagnostic_table <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb21-21">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Check =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Zero frequency"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Dispersion"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Overall uniformity"</span>),</span>
<span id="cb21-22">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Statistic shown</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb21-23">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Observed/simulated zeros"</span>,</span>
<span id="cb21-24">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Observed/simulated spread"</span>,</span>
<span id="cb21-25">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"KS D (uniformity)"</span></span>
<span id="cb21-26">  ),</span>
<span id="cb21-27">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Negative binomial</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb21-28">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format_diagnostic</span>(nb_zero_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>statistic, nb_zero_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value),</span>
<span id="cb21-29">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format_diagnostic</span>(</span>
<span id="cb21-30">      nb_dispersion_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>statistic,</span>
<span id="cb21-31">      nb_dispersion_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value</span>
<span id="cb21-32">    ),</span>
<span id="cb21-33">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format_diagnostic</span>(</span>
<span id="cb21-34">      nb_uniformity_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>statistic,</span>
<span id="cb21-35">      nb_uniformity_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value,</span>
<span id="cb21-36">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb21-37">    )</span>
<span id="cb21-38">  ),</span>
<span id="cb21-39">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Compact ZINB</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb21-40">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format_diagnostic</span>(zinb_zero_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>statistic, zinb_zero_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value),</span>
<span id="cb21-41">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format_diagnostic</span>(</span>
<span id="cb21-42">      zinb_dispersion_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>statistic,</span>
<span id="cb21-43">      zinb_dispersion_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value</span>
<span id="cb21-44">    ),</span>
<span id="cb21-45">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format_diagnostic</span>(</span>
<span id="cb21-46">      zinb_uniformity_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>statistic,</span>
<span id="cb21-47">      zinb_uniformity_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value,</span>
<span id="cb21-48">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb21-49">    )</span>
<span id="cb21-50">  )</span>
<span id="cb21-51">)</span>
<span id="cb21-52"></span>
<span id="cb21-53">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(diagnostic_table, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>))</span></code></pre></div></div>
</details>
<div id="tbl-candidate-diagnostic-tests" class="cell quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-candidate-diagnostic-tests-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;10: Simulation checks for the negative-binomial benchmark and compact ZINB.
</figcaption>
<div aria-describedby="tbl-candidate-diagnostic-tests-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output-display">
<table class="cell caption-top table table-sm table-striped small">
<colgroup>
<col style="width: 23%">
<col style="width: 31%">
<col style="width: 21%">
<col style="width: 23%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">Check</th>
<th style="text-align: left;">Statistic shown</th>
<th style="text-align: right;">Negative binomial</th>
<th style="text-align: right;">Compact ZINB</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Zero frequency</td>
<td style="text-align: left;">Observed/simulated zeros</td>
<td style="text-align: right;">1.10 (p = 0.008)</td>
<td style="text-align: right;">0.97 (p = 0.27)</td>
</tr>
<tr class="even">
<td style="text-align: left;">Dispersion</td>
<td style="text-align: left;">Observed/simulated spread</td>
<td style="text-align: right;">1.06 (p = 0.3)</td>
<td style="text-align: right;">1.18 (p = 0.002)</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Overall uniformity</td>
<td style="text-align: left;">KS D (uniformity)</td>
<td style="text-align: right;">0.024 (p = 0.014)</td>
<td style="text-align: right;">0.029 (p = 0.0013)</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</div>
<p>The zero-frequency row returns to the discrepancy that motivated the ZINB. The negative-binomial model produces too few zeros: the observed number is 1.10 times its simulated expectation (<img src="https://latex.codecogs.com/png.latex?p%20=%200.008">). For the compact ZINB, the ratio falls to 0.97 (<img src="https://latex.codecogs.com/png.latex?p%20=%200.27">). The extra-zero component therefore brings the overall number of zeros into line with the simulations. The remaining rows broaden the assessment to residual spread and the full residual distribution.</p>
<p>The dispersion row reverses the comparison. NB’s ratio of 1.06 is consistent with its simulations, whereas the ZINB ratio is 1.18 (<img src="https://latex.codecogs.com/png.latex?p%20=%200.002">). The ZINB residual spread differs from its simulated expectation by about 18%, a noticeable as well as statistically significant departure.</p>
<p>Both models also depart from uniformity. The Kolmogorov–Smirnov (KS) statistic <img src="https://latex.codecogs.com/png.latex?D"> is the largest vertical gap between the empirical cumulative distribution of the residuals and the uniform reference distribution. For the compact ZINB, <img src="https://latex.codecogs.com/png.latex?D%20=%200.029"> corresponds to a maximum gap of 2.9 percentage points. Its <img src="https://latex.codecogs.com/png.latex?p">-value of 0.0013 is the probability, under uniform residuals, of obtaining a maximum gap at least this large. The zero component repairs the zero frequency, while the dispersion and uniformity results identify broader discrepancies to investigate.</p>
<p>The standard DHARMa display in Figure&nbsp;5 brings these results together. The left panel is a uniform QQ plot: residuals from a calibrated model should follow the diagonal. The accompanying labels report the KS uniformity, dispersion, and outlier checks; of these, the KS test corresponds directly to the QQ comparison.</p>
<p>In the right panel, I replace DHARMa’s default quantile regressions with a single smooth line showing how the average residual changes across rank-transformed fitted values. The line should remain close to 0.5 throughout. A red star marks an observation whose count falls below every simulated value or above every simulated value for that participant. The later covariate plots follow the 25th, 50th, and 75th residual quantiles separately.</p>
<div class="cell">
<details class="code-fold">
<summary>Show overall residual-plot code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb22-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(</span>
<span id="cb22-2">  zinb_residuals,</span>
<span id="cb22-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quantreg =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb22-4">)</span></code></pre></div></div>
</details>
<div class="cell-output-display">
<div id="fig-zinb-diagnostics" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Two DHARMa panels for compact ZINB. The left compares observed residual quantiles with expected uniform quantiles and reports significant uniformity, dispersion, and outlier checks. The right shows scaled residual points against rank-transformed predictions. A black smoother stays near one-half but bends slightly at the ends, and observations outside the range of all their simulated values are marked with red stars.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-zinb-diagnostics-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://andreadifra.github.io/posts/zero-inflated-models-tutorial/index_files/figure-html/fig-zinb-diagnostics-1.png" class="img-fluid figure-img" alt="Two DHARMa panels for compact ZINB. The left compares observed residual quantiles with expected uniform quantiles and reports significant uniformity, dispersion, and outlier checks. The right shows scaled residual points against rank-transformed predictions. A black smoother stays near one-half but bends slightly at the ends, and observations outside the range of all their simulated values are marked with red stars." width="960">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-zinb-diagnostics-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;5: Overall simulated-residual diagnostics for the compact ZINB. The QQ comparison is close to the diagonal but statistically non-uniform; residuals against fitted values remain broadly centred while some observed counts fall beyond all values simulated for the same participant.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The QQ curve lies close to the diagonal, and the right-panel smoother stays near 0.5 through most of the fitted range. Across the 4,406 observations, the diagnostic statistics pick up small but consistent departures. The next checks trace those departures through the observed count frequencies and covariates.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-10-contents" aria-controls="callout-10" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Bootstrap outlier check
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-10" class="callout-10-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>DHARMa calls an observation a simulation outlier when its observed count falls below or above every value simulated for that participant. Some such cases arise even under a well-fitting model, and their expected frequency depends on the number of simulations. For integer outcomes, the simple theoretical approximation can be inaccurate, so the bootstrap applies the same outside-the-simulated-range rule to data generated under the fitted model.</p>
<p>The <a href="https://stat.ethz.ch/CRAN/web/packages/DHARMa/refman/DHARMa.html#testOutliers"><code>testOutliers()</code> reference</a> recommends at least 1,000 simulations and 1,000 bootstrap replicates for integer-valued outcomes. Here the bootstrap estimates how often observations should fall beyond all their simulated values and compares that expectation with the observed frequency.</p>
<div class="cell">
<details class="code-fold">
<summary>Show bootstrap outlier-test code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb23-1">zinb_outlier_test <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">testOutliers</span>(</span>
<span id="cb23-2">  zinb_residuals,</span>
<span id="cb23-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bootstrap"</span>,</span>
<span id="cb23-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nBoot =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>,</span>
<span id="cb23-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb23-6">)</span>
<span id="cb23-7"></span>
<span id="cb23-8">outlier_table <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb23-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Quantity =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb23-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Observed counts beyond all simulated values"</span>,</span>
<span id="cb23-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Expected 95% frequency range under the fitted model"</span>,</span>
<span id="cb23-12">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bootstrap comparison"</span></span>
<span id="cb23-13">  ),</span>
<span id="cb23-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Result =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb23-15">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(</span>
<span id="cb23-16">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%d of %s (%.2f%%)"</span>,</span>
<span id="cb23-17">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unname</span>(zinb_outlier_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>statistic),</span>
<span id="cb23-18">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span>(</span>
<span id="cb23-19">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unname</span>(zinb_outlier_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>parameter),</span>
<span id="cb23-20">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">big.mark =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>,</span>
<span id="cb23-21">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scientific =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb23-22">      ),</span>
<span id="cb23-23">      <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unname</span>(zinb_outlier_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>estimate)</span>
<span id="cb23-24">    ),</span>
<span id="cb23-25">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(</span>
<span id="cb23-26">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f%%–%.2f%%"</span>,</span>
<span id="cb23-27">      <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unname</span>(zinb_outlier_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conf.int[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]),</span>
<span id="cb23-28">      <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unname</span>(zinb_outlier_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>conf.int[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>])</span>
<span id="cb23-29">    ),</span>
<span id="cb23-30">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(</span>
<span id="cb23-31">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p"</span>,</span>
<span id="cb23-32">      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (zinb_outlier_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>) {</span>
<span id="cb23-33">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt; 0.001"</span></span>
<span id="cb23-34">      } <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> {</span>
<span id="cb23-35">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"="</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(zinb_outlier_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb23-36">      }</span>
<span id="cb23-37">    )</span>
<span id="cb23-38">  )</span>
<span id="cb23-39">)</span>
<span id="cb23-40"></span>
<span id="cb23-41">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(outlier_table, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>))</span></code></pre></div></div>
</details>
<div id="tbl-zinb-outlier-bootstrap" class="cell quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-zinb-outlier-bootstrap-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;11: Bootstrap check of observations beyond the simulated range for the compact ZINB.
</figcaption>
<div aria-describedby="tbl-zinb-outlier-bootstrap-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output-display">
<table class="cell caption-top table table-sm table-striped small">
<colgroup>
<col style="width: 72%">
<col style="width: 27%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">Quantity</th>
<th style="text-align: left;">Result</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Observed counts beyond all simulated values</td>
<td style="text-align: left;">20 of 4,406 (0.45%)</td>
</tr>
<tr class="even">
<td style="text-align: left;">Expected 95% frequency range under the fitted model</td>
<td style="text-align: left;">0.05%–0.25%</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Bootstrap comparison</td>
<td style="text-align: left;">p &lt; 0.001</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</div>
<p>The compact ZINB produces 20 observations beyond the simulated range, compared with the much lower frequency expected under the fitted model. This result can arise from misspecified tails, unusual but valid observations, or data errors; the test does not distinguish among them. Individual records should be removed only when an independent data-quality check shows that they are invalid. Otherwise, they remain part of the evidence used to refine the model.</p>
</div>
</div>
</div>
<p>We next return from scaled residuals to the visit counts themselves. Figure&nbsp;6 compares the observed frequency of each count with the range generated by the same simulations, using the earlier NB model as a benchmark.</p>
<div class="cell">
<details class="code-fold">
<summary>Show count-frequency check code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb24-1">summarise_count_frequencies <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(residuals, model_name) {</span>
<span id="cb24-2">  simulated <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> residuals<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>simulatedResponse</span>
<span id="cb24-3">  observed <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>ofp</span>
<span id="cb24-4">  displayed_counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span></span>
<span id="cb24-5">  count_labels <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.character</span>(displayed_counts), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"16+"</span>)</span>
<span id="cb24-6"></span>
<span id="cb24-7">  simulated_counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb24-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(displayed_counts, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(value) {</span>
<span id="cb24-9">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colSums</span>(simulated <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> value)</span>
<span id="cb24-10">    }),</span>
<span id="cb24-11">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colSums</span>(simulated <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>))</span>
<span id="cb24-12">  )</span>
<span id="cb24-13"></span>
<span id="cb24-14">  tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb24-15">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Model =</span> model_name,</span>
<span id="cb24-16">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Count =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(count_labels, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> count_labels),</span>
<span id="cb24-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Observed =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb24-18">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(</span>
<span id="cb24-19">        displayed_counts,</span>
<span id="cb24-20">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(value) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(observed <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> value),</span>
<span id="cb24-21">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb24-22">      ),</span>
<span id="cb24-23">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(observed <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>)</span>
<span id="cb24-24">    ),</span>
<span id="cb24-25">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Simulated median</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(</span>
<span id="cb24-26">      simulated_counts,</span>
<span id="cb24-27">      median,</span>
<span id="cb24-28">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb24-29">    ),</span>
<span id="cb24-30">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Lower =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(</span>
<span id="cb24-31">      simulated_counts,</span>
<span id="cb24-32">      quantile,</span>
<span id="cb24-33">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb24-34">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">probs =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.025</span>,</span>
<span id="cb24-35">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb24-36">    ),</span>
<span id="cb24-37">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Upper =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(</span>
<span id="cb24-38">      simulated_counts,</span>
<span id="cb24-39">      quantile,</span>
<span id="cb24-40">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb24-41">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">probs =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.975</span>,</span>
<span id="cb24-42">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb24-43">    )</span>
<span id="cb24-44">  )</span>
<span id="cb24-45">}</span>
<span id="cb24-46"></span>
<span id="cb24-47">count_frequency_check <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bind_rows</span>(</span>
<span id="cb24-48">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise_count_frequencies</span>(</span>
<span id="cb24-49">    nb_residuals,</span>
<span id="cb24-50">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Negative-binomial benchmark"</span></span>
<span id="cb24-51">  ),</span>
<span id="cb24-52">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise_count_frequencies</span>(</span>
<span id="cb24-53">    zinb_residuals,</span>
<span id="cb24-54">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Compact ZINB"</span></span>
<span id="cb24-55">  )</span>
<span id="cb24-56">) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb24-57">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(</span>
<span id="cb24-58">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Model =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(</span>
<span id="cb24-59">      Model,</span>
<span id="cb24-60">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb24-61">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Negative-binomial benchmark"</span>,</span>
<span id="cb24-62">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Compact ZINB"</span></span>
<span id="cb24-63">      )</span>
<span id="cb24-64">    )</span>
<span id="cb24-65">  )</span>
<span id="cb24-66"></span>
<span id="cb24-67"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(count_frequency_check, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> Count)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb24-68">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_linerange</span>(</span>
<span id="cb24-69">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(</span>
<span id="cb24-70">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ymin =</span> Lower,</span>
<span id="cb24-71">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ymax =</span> Upper,</span>
<span id="cb24-72">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"95% simulation interval"</span></span>
<span id="cb24-73">    ),</span>
<span id="cb24-74">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span></span>
<span id="cb24-75">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb24-76">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(</span>
<span id="cb24-77">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Simulated median</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Simulated median"</span>),</span>
<span id="cb24-78">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">shape =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">95</span>,</span>
<span id="cb24-79">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span></span>
<span id="cb24-80">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb24-81">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(</span>
<span id="cb24-82">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> Observed, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Observed frequency"</span>),</span>
<span id="cb24-83">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb24-84">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb24-85">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vars</span>(Model), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ncol =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb24-86">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(</span>
<span id="cb24-87">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb24-88">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"95% simulation interval"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#5B8DB8"</span>,</span>
<span id="cb24-89">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Simulated median"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1F4E79"</span>,</span>
<span id="cb24-90">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Observed frequency"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#B23A33"</span></span>
<span id="cb24-91">    )</span>
<span id="cb24-92">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb24-93">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb24-94">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Physician office visits"</span>,</span>
<span id="cb24-95">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of participants"</span>,</span>
<span id="cb24-96">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span></span>
<span id="cb24-97">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb24-98">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb24-99">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(</span>
<span id="cb24-100">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>,</span>
<span id="cb24-101">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>()</span>
<span id="cb24-102">  )</span></code></pre></div></div>
</details>
<div class="cell-output-display">
<div id="fig-count-frequency-check" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Two panels compare observed visit-count frequencies with simulation intervals for negative binomial and compact ZINB. Negative binomial simulates too few zeros and too many counts of one and two. Compact ZINB aligns much more closely with the observed zero and low-count frequencies, although aggregate agreement does not remove conditional residual departures.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-count-frequency-check-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://andreadifra.github.io/posts/zero-inflated-models-tutorial/index_files/figure-html/fig-count-frequency-check-1.png" class="img-fluid figure-img" alt="Two panels compare observed visit-count frequencies with simulation intervals for negative binomial and compact ZINB. Negative binomial simulates too few zeros and too many counts of one and two. Compact ZINB aligns much more closely with the observed zero and low-count frequencies, although aggregate agreement does not remove conditional residual departures." width="960">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-count-frequency-check-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;6: Observed and simulated count frequencies under the negative-binomial benchmark and compact ZINB. Intervals contain the central 95% of frequencies across 1,000 simulated datasets; counts of 16 or more are pooled.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The NB panel shows the discrepancy already identified earlier: the observed zero count lies above its simulation interval, while counts of one and two are overproduced. The compact ZINB brings the zero and low-count frequencies much closer to the data. However, this marginal agreement can still conceal conditional problems because it pools participants with different fitted distributions.</p>
<p>To locate those problems, Figure&nbsp;7 groups the ZINB residuals by age and chronic-condition count. A uniform residual distribution would place the three displayed quantiles on the dashed 0.25, 0.50, and 0.75 reference lines within every group.</p>
<div class="cell">
<details class="code-fold">
<summary>Show covariate-residual check code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb25-1">age_levels <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb25-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"66–69"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"70–74"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"75–79"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"80–84"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"85–89"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"90+"</span></span>
<span id="cb25-3">)</span>
<span id="cb25-4">chronic_levels <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"0"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"4"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"5"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"6+"</span>)</span>
<span id="cb25-5"></span>
<span id="cb25-6">residual_covariates <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb25-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Residual =</span> zinb_residuals<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaledResiduals,</span>
<span id="cb25-8">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Age band</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cut</span>(</span>
<span id="cb25-9">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>age <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>),</span>
<span id="cb25-10">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">65</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">69</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">74</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">79</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">84</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">89</span>, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">Inf</span>),</span>
<span id="cb25-11">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> age_levels</span>
<span id="cb25-12">  ),</span>
<span id="cb25-13">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Chronic conditions</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(</span>
<span id="cb25-14">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>numchron <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"6+"</span>, medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>numchron),</span>
<span id="cb25-15">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> chronic_levels</span>
<span id="cb25-16">  )</span>
<span id="cb25-17">)</span>
<span id="cb25-18"></span>
<span id="cb25-19">age_quantiles <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> residual_covariates <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb25-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Age band</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb25-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise</span>(</span>
<span id="cb25-22">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Q25 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(Residual, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>),</span>
<span id="cb25-23">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Median =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(Residual),</span>
<span id="cb25-24">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Q75 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(Residual, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.75</span>),</span>
<span id="cb25-25">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.groups =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"drop"</span></span>
<span id="cb25-26">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb25-27">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rename</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Level =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Age band</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>)</span>
<span id="cb25-28"></span>
<span id="cb25-29">chronic_quantiles <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> residual_covariates <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb25-30">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Chronic conditions</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb25-31">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise</span>(</span>
<span id="cb25-32">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Q25 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(Residual, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>),</span>
<span id="cb25-33">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Median =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(Residual),</span>
<span id="cb25-34">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Q75 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(Residual, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.75</span>),</span>
<span id="cb25-35">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.groups =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"drop"</span></span>
<span id="cb25-36">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb25-37">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rename</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Level =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Chronic conditions</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span>)</span>
<span id="cb25-38"></span>
<span id="cb25-39">to_long_quantiles <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(data, panel_name) {</span>
<span id="cb25-40">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bind_rows</span>(</span>
<span id="cb25-41">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transmute</span>(</span>
<span id="cb25-42">      data,</span>
<span id="cb25-43">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Panel =</span> panel_name,</span>
<span id="cb25-44">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Level =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.character</span>(Level),</span>
<span id="cb25-45">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Quantile =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"25th"</span>,</span>
<span id="cb25-46">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Value =</span> Q25</span>
<span id="cb25-47">    ),</span>
<span id="cb25-48">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transmute</span>(</span>
<span id="cb25-49">      data,</span>
<span id="cb25-50">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Panel =</span> panel_name,</span>
<span id="cb25-51">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Level =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.character</span>(Level),</span>
<span id="cb25-52">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Quantile =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Median"</span>,</span>
<span id="cb25-53">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Value =</span> Median</span>
<span id="cb25-54">    ),</span>
<span id="cb25-55">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transmute</span>(</span>
<span id="cb25-56">      data,</span>
<span id="cb25-57">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Panel =</span> panel_name,</span>
<span id="cb25-58">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Level =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.character</span>(Level),</span>
<span id="cb25-59">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Quantile =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"75th"</span>,</span>
<span id="cb25-60">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Value =</span> Q75</span>
<span id="cb25-61">    )</span>
<span id="cb25-62">  )</span>
<span id="cb25-63">}</span>
<span id="cb25-64"></span>
<span id="cb25-65">covariate_quantiles <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bind_rows</span>(</span>
<span id="cb25-66">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to_long_quantiles</span>(age_quantiles, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Age band (years)"</span>),</span>
<span id="cb25-67">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to_long_quantiles</span>(chronic_quantiles, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chronic conditions"</span>)</span>
<span id="cb25-68">) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb25-69">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(</span>
<span id="cb25-70">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Level =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(Level, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(age_levels, chronic_levels)),</span>
<span id="cb25-71">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Quantile =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(</span>
<span id="cb25-72">      Quantile,</span>
<span id="cb25-73">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"25th"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Median"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"75th"</span>)</span>
<span id="cb25-74">    )</span>
<span id="cb25-75">  )</span>
<span id="cb25-76"></span>
<span id="cb25-77"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(</span>
<span id="cb25-78">  covariate_quantiles,</span>
<span id="cb25-79">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> Level, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> Value, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> Quantile, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> Quantile)</span>
<span id="cb25-80">) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb25-81">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(</span>
<span id="cb25-82">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.75</span>),</span>
<span id="cb25-83">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>,</span>
<span id="cb25-84">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#8A8A8A"</span>,</span>
<span id="cb25-85">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span></span>
<span id="cb25-86">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb25-87">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb25-88">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb25-89">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vars</span>(Panel), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scales =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"free_x"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ncol =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb25-90">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_colour_manual</span>(</span>
<span id="cb25-91">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb25-92">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"25th"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#0072B2"</span>,</span>
<span id="cb25-93">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Median"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#222222"</span>,</span>
<span id="cb25-94">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"75th"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#D55E00"</span></span>
<span id="cb25-95">    )</span>
<span id="cb25-96">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb25-97">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(</span>
<span id="cb25-98">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">limits =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb25-99">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.75</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb25-100">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb25-101">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb25-102">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>,</span>
<span id="cb25-103">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DHARMa scaled-residual quantile"</span>,</span>
<span id="cb25-104">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Within-group quantile"</span></span>
<span id="cb25-105">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb25-106">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb25-107">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(</span>
<span id="cb25-108">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>,</span>
<span id="cb25-109">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>()</span>
<span id="cb25-110">  )</span></code></pre></div></div>
</details>
<div class="cell-output-display">
<div id="fig-zinb-continuous-residuals" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Two line charts show the 25th, median, and 75th DHARMa residual quantiles. Residual quantiles drift downward in the oldest age bands and vary across chronic-condition groups instead of remaining on their uniform reference lines.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-zinb-continuous-residuals-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://andreadifra.github.io/posts/zero-inflated-models-tutorial/index_files/figure-html/fig-zinb-continuous-residuals-1.png" class="img-fluid figure-img" alt="Two line charts show the 25th, median, and 75th DHARMa residual quantiles. Residual quantiles drift downward in the oldest age bands and vary across chronic-condition groups instead of remaining on their uniform reference lines." width="960">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-zinb-continuous-residuals-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;7: Compact-ZINB residual quantiles across age and chronic-condition groups. Dashed lines mark the 0.25, 0.50, and 0.75 quantiles expected from uniform residuals; ages 90 and older and counts of six or more are pooled because those observations are sparse.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The age quantiles drift below their references among the oldest participants, rather than continuing the near-flat pattern implied by a single linear age term. Chronic-condition groups also vary, particularly at the low and high ends of the observed range. The plots locate the clearest departures in these parts of the data. Either the count mean, the extra-zero probability, or a combination of the two could produce the patterns.</p>
<p>The remaining binary predictors could hide group-specific departures or suggest an omitted interaction. Figure&nbsp;8 therefore compares the residual distributions across health status, sex, and marital status. For uniform residuals, each box should have a median near 0.5 and its lower and upper edges near 0.25 and 0.75.</p>
<div class="cell">
<details class="code-fold">
<summary>Show grouped-residual check code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb26-1">health_status <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(</span>
<span id="cb26-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(</span>
<span id="cb26-3">    medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>healthpoor <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb26-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poor"</span>,</span>
<span id="cb26-5">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>healthexcellent <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Excellent"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Average"</span>)</span>
<span id="cb26-6">  ),</span>
<span id="cb26-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Average"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poor"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Excellent"</span>)</span>
<span id="cb26-8">)</span>
<span id="cb26-9"></span>
<span id="cb26-10">group_residuals <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bind_rows</span>(</span>
<span id="cb26-11">  tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb26-12">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Panel =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Health status"</span>,</span>
<span id="cb26-13">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Level =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.character</span>(health_status),</span>
<span id="cb26-14">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Residual =</span> zinb_residuals<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaledResiduals</span>
<span id="cb26-15">  ),</span>
<span id="cb26-16">  tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb26-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Panel =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sex"</span>,</span>
<span id="cb26-18">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Level =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>male <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Male"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Female"</span>),</span>
<span id="cb26-19">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Residual =</span> zinb_residuals<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaledResiduals</span>
<span id="cb26-20">  ),</span>
<span id="cb26-21">  tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb26-22">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Panel =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Marital status"</span>,</span>
<span id="cb26-23">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Level =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ifelse</span>(</span>
<span id="cb26-24">      medcare<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>married <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb26-25">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Married"</span>,</span>
<span id="cb26-26">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Not married"</span></span>
<span id="cb26-27">    ),</span>
<span id="cb26-28">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Residual =</span> zinb_residuals<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>scaledResiduals</span>
<span id="cb26-29">  )</span>
<span id="cb26-30">) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb26-31">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(</span>
<span id="cb26-32">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Panel =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(</span>
<span id="cb26-33">      Panel,</span>
<span id="cb26-34">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Health status"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sex"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Marital status"</span>)</span>
<span id="cb26-35">    ),</span>
<span id="cb26-36">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Level =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(</span>
<span id="cb26-37">      Level,</span>
<span id="cb26-38">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb26-39">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Average"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poor"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Excellent"</span>,</span>
<span id="cb26-40">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Female"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Male"</span>,</span>
<span id="cb26-41">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Not married"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Married"</span></span>
<span id="cb26-42">      )</span>
<span id="cb26-43">    )</span>
<span id="cb26-44">  )</span>
<span id="cb26-45"></span>
<span id="cb26-46"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(group_residuals, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> Level, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> Residual)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb26-47">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(</span>
<span id="cb26-48">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.75</span>),</span>
<span id="cb26-49">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>,</span>
<span id="cb26-50">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#8A8A8A"</span>,</span>
<span id="cb26-51">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linewidth =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span></span>
<span id="cb26-52">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb26-53">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_boxplot</span>(</span>
<span id="cb26-54">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#D9E8F5"</span>,</span>
<span id="cb26-55">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colour =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#1F4E79"</span>,</span>
<span id="cb26-56">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.62</span>,</span>
<span id="cb26-57">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outlier.alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.15</span>,</span>
<span id="cb26-58">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outlier.size =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span></span>
<span id="cb26-59">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb26-60">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vars</span>(Panel), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scales =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"free_x"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ncol =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb26-61">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(</span>
<span id="cb26-62">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">limits =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb26-63">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.25</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.75</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb26-64">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb26-65">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb26-66">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span>,</span>
<span id="cb26-67">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DHARMa scaled residual"</span></span>
<span id="cb26-68">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb26-69">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb26-70">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.grid.minor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>())</span></code></pre></div></div>
</details>
<div class="cell-output-display">
<div id="fig-zinb-group-residuals" class="quarto-float quarto-figure quarto-figure-center anchored" alt="Three panels contain residual boxplots for health-status, sex, and marital-status groups. Group medians and interquartile ranges are broadly similar, with no pronounced between-group shift despite the model's overall residual departures.">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-zinb-group-residuals-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://andreadifra.github.io/posts/zero-inflated-models-tutorial/index_files/figure-html/fig-zinb-group-residuals-1.png" class="img-fluid figure-img" alt="Three panels contain residual boxplots for health-status, sex, and marital-status groups. Group medians and interquartile ranges are broadly similar, with no pronounced between-group shift despite the model's overall residual departures." width="960">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-zinb-group-residuals-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;8: Compact-ZINB residual distributions across health status, sex, and marital status. Dashed lines mark the quartiles expected from a uniform distribution.
</figcaption>
</figure>
</div>
</div>
</div>
<p>The group distributions are broadly similar, with no particular health, sex, or marital-status interaction standing out as the next addition. The age and chronic-condition patterns offer clearer directions for further work. A fuller analysis could compare substantively motivated nonlinear terms in the count mean, the extra-zero equation, or both, and evaluate them with out-of-sample data or resampling. Adding a quadratic term chosen from these same residual plots would instead combine model development and assessment in one step.</p>
<p>Together, these standard checks show that the compact ZINB reproduces the overall zero and low-count frequencies much better than the negative-binomial benchmark. The remaining departures are meaningful but limited in magnitude: residual spread is about 18% above its simulated expectation, the largest uniformity gap is 2.9 percentage points, and 20 of 4,406 observations (0.45%) fall beyond all their simulated values. The age and chronic-condition plots locate further discrepancies mainly at the ends of their observed ranges. The small p-values make these patterns unlikely to be simulation noise; their absolute size and location determine how much they matter in practice.</p>
<p>These results support a calculated working-model choice, and for the sake of this tutorial, I retain the compact ZINB as an <strong>illustrative working model</strong> because it is effectively tied for the lowest AIC, has the lowest BIC, repairs the main zero-frequency discrepancy, and directly represents the two-process question of interest. A fuller analysis would compare substantively motivated nonlinear terms, interactions, and alternative specifications, preferably with out-of-sample assessment. The next subsection interprets the fitted components while carrying these diagnostic limitations into the conclusions.</p>
</section>
<section id="interpreting-the-zero-inflated-model" class="level2" data-number="5.5">
<h2 data-number="5.5" class="anchored" data-anchor-id="interpreting-the-zero-inflated-model"><span class="header-section-number">5.5</span> Interpreting the Zero-Inflated Model</h2>
<p>A zero-inflated regression offers two related views of the fitted associations. We first examine <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> and <img src="https://latex.codecogs.com/png.latex?%5Cpi_i"> separately to see whether each predictor acts through the count-generating state, the latent extra-zero state, or both. We then recombine the two components on the observed response scale, where their associations may reinforce or offset one another. The first view explains how the model represents the data; the second gives the practical interpretation in expected visits.</p>
<section id="component-specific-associations" class="level3" data-number="5.5.1">
<h3 data-number="5.5.1" class="anchored" data-anchor-id="component-specific-associations"><span class="header-section-number">5.5.1</span> Component-Specific Associations</h3>
<p>Building on the regression formulation, we interpret the illustrative working model in two passes: <img src="https://latex.codecogs.com/png.latex?%5Cmu_i">, the conditional mean number of visits in the count-generating state, and <img src="https://latex.codecogs.com/png.latex?%5Cpi_i">, the probability assigned to the latent extra-zero state. Exponentiating their regression coefficients gives multiplicative associations with the count-component conditional mean and with the odds assigned to the extra-zero state, respectively.</p>
<div class="cell">
<details class="code-fold">
<summary>Show count-component interpretation code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb27" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb27-1">count_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model_parameters</span>(</span>
<span id="cb27-2">  zinb_model,</span>
<span id="cb27-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">component =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"conditional"</span>,</span>
<span id="cb27-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">effects =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fixed"</span>,</span>
<span id="cb27-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">exponentiate =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb27-6">) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb27-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(Parameter <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"(Intercept)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb27-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transmute</span>(</span>
<span id="cb27-9">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Predictor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">recode</span>(</span>
<span id="cb27-10">      Parameter,</span>
<span id="cb27-11">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">healthpoor =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poor vs average health"</span>,</span>
<span id="cb27-12">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">healthexcellent =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Excellent vs average health"</span>,</span>
<span id="cb27-13">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">numchron =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chronic conditions (per condition)"</span>,</span>
<span id="cb27-14">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">age =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Age (per decade)"</span>,</span>
<span id="cb27-15">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">male =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Male vs female"</span>,</span>
<span id="cb27-16">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">married =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Married vs not married"</span></span>
<span id="cb27-17">    ),</span>
<span id="cb27-18">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Conditional-mean ratio</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f"</span>, Coefficient),</span>
<span id="cb27-19">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">95% CI</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f–%.2f"</span>, CI_low, CI_high),</span>
<span id="cb27-20">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p-value</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">eps =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>)</span>
<span id="cb27-21">  )</span>
<span id="cb27-22"></span>
<span id="cb27-23">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(count_df, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"c"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span></code></pre></div></div>
</details>
<div id="tbl-zinb-count-effects" class="cell quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-zinb-count-effects-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;12: Count component: multiplicative associations with the count-component conditional mean.
</figcaption>
<div aria-describedby="tbl-zinb-count-effects-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output-display">
<table class="cell caption-top table table-sm table-striped small">
<colgroup>
<col style="width: 45%">
<col style="width: 29%">
<col style="width: 14%">
<col style="width: 10%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">Predictor</th>
<th style="text-align: right;">Conditional-mean ratio</th>
<th style="text-align: center;">95% CI</th>
<th style="text-align: right;">p-value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Poor vs average health</td>
<td style="text-align: right;">1.32</td>
<td style="text-align: center;">1.21–1.44</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
<tr class="even">
<td style="text-align: left;">Excellent vs average health</td>
<td style="text-align: right;">0.73</td>
<td style="text-align: center;">0.65–0.82</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Chronic conditions (per condition)</td>
<td style="text-align: right;">1.16</td>
<td style="text-align: center;">1.14–1.19</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
<tr class="even">
<td style="text-align: left;">Age (per decade)</td>
<td style="text-align: right;">0.95</td>
<td style="text-align: center;">0.90–0.99</td>
<td style="text-align: right;">0.027</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Male vs female</td>
<td style="text-align: right;">0.98</td>
<td style="text-align: center;">0.91–1.05</td>
<td style="text-align: right;">0.485</td>
</tr>
<tr class="even">
<td style="text-align: left;">Married vs not married</td>
<td style="text-align: right;">0.94</td>
<td style="text-align: center;">0.87–1.01</td>
<td style="text-align: right;">0.077</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</div>
<div class="cell">
<details class="code-fold">
<summary>Show zero-inflation-component interpretation code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb28-1">zi_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">model_parameters</span>(</span>
<span id="cb28-2">  zinb_model,</span>
<span id="cb28-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">component =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"zero_inflated"</span>,</span>
<span id="cb28-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">effects =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fixed"</span>,</span>
<span id="cb28-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">exponentiate =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span id="cb28-6">) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb28-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(Parameter <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"(Intercept)"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb28-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transmute</span>(</span>
<span id="cb28-9">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Predictor =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">recode</span>(</span>
<span id="cb28-10">      Parameter,</span>
<span id="cb28-11">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">healthpoor =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Poor vs average health"</span>,</span>
<span id="cb28-12">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">healthexcellent =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Excellent vs average health"</span>,</span>
<span id="cb28-13">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">numchron =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chronic conditions (per condition)"</span>,</span>
<span id="cb28-14">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">age =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Age (per decade)"</span>,</span>
<span id="cb28-15">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">male =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Male vs female"</span>,</span>
<span id="cb28-16">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">married =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Married vs not married"</span></span>
<span id="cb28-17">    ),</span>
<span id="cb28-18">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Odds ratio</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f"</span>, Coefficient),</span>
<span id="cb28-19">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">95% CI</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f–%.2f"</span>, CI_low, CI_high),</span>
<span id="cb28-20">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p-value</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format.pval</span>(p, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">digits =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">eps =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>)</span>
<span id="cb28-21">  )</span>
<span id="cb28-22"></span>
<span id="cb28-23">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(zi_df, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"c"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span></code></pre></div></div>
</details>
<div id="tbl-zinb-zero-effects" class="cell quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-zinb-zero-effects-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;13: Zero component: multiplicative associations with the odds assigned to the latent extra-zero state.
</figcaption>
<div aria-describedby="tbl-zinb-zero-effects-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output-display">
<table class="cell caption-top table table-sm table-striped small">
<thead>
<tr class="header">
<th style="text-align: left;">Predictor</th>
<th style="text-align: right;">Odds ratio</th>
<th style="text-align: center;">95% CI</th>
<th style="text-align: right;">p-value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Chronic conditions (per condition)</td>
<td style="text-align: right;">0.28</td>
<td style="text-align: center;">0.19–0.41</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
<tr class="even">
<td style="text-align: left;">Male vs female</td>
<td style="text-align: right;">3.08</td>
<td style="text-align: center;">1.84–5.16</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Married vs not married</td>
<td style="text-align: right;">0.35</td>
<td style="text-align: center;">0.21–0.59</td>
<td style="text-align: right;">&lt;0.001</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</div>
<p><strong><img src="https://latex.codecogs.com/png.latex?%5Cmu_i">:</strong> within the count-generating state, the count-component conditional mean is 16% higher for each additional chronic condition (conditional-mean ratio 1.16, 95% CI 1.14–1.19) and 32% higher for poor rather than average health (1.32, 95% CI 1.21–1.44). Excellent rather than average health is associated with a 27% lower conditional mean (0.73, 95% CI 0.65–0.82), while each additional decade of age is associated with a 5% lower conditional mean (0.95, 95% CI 0.90–0.99). The estimates for sex and marital status are close to 1, and their confidence intervals include 1.</p>
<p><strong><img src="https://latex.codecogs.com/png.latex?%5Cpi_i">:</strong> each additional chronic condition is associated with 72% lower odds assigned to the latent extra-zero state (odds ratio 0.28, 95% CI 0.19–0.41). The fitted odds are higher for men than women (3.08, 95% CI 1.84–5.16) and lower for married participants than for participants who were not married (0.35, 95% CI 0.21–0.59). Here, the odds refer only to a modelled latent-state probability. Observed-zero odds and membership in a known patient group are different quantities.</p>
<p>It’s important to note that the reported intervals and p-values assume that the compact formula was fixed in advance, although its predictors were informed partly by observed-zero associations in these data. Specification selection therefore adds uncertainty beyond the reported coefficient estimates. We treat every association as a descriptive summary of the fitted specification, without a causal or individual-classification interpretation.</p>
</section>
<section id="overall-expected-visits" class="level3" data-number="5.5.2">
<h3 data-number="5.5.2" class="anchored" data-anchor-id="overall-expected-visits"><span class="header-section-number">5.5.2</span> Overall Expected Visits</h3>
<p>The component tables describe <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> and <img src="https://latex.codecogs.com/png.latex?%5Cpi_i"> separately, but neither component alone tells us how expected visits change. A predictor can shift the count mean, the extra-zero probability, or both; those shifts may reinforce or offset one another. We therefore combine them in the original outcome units as <img src="https://latex.codecogs.com/png.latex?(1-%5Cpi_i)%5Cmu_i">.</p>
<p>To see what the two pathways imply together, we create two versions of each eligible record. We change the predictor of interest, retain the observed values of every other predictor, and calculate overall expected visits for both versions. Averaging those predictions across the eligible records gives two standardized means; their difference and ratio form the <strong>standardized contrast</strong> reported in Table&nbsp;14. We report three such comparisons:</p>
<ul>
<li><strong>Sex and marriage:</strong> set the relevant binary indicator to 0 for every record in the reference version and to 1 in the comparison version.</li>
<li><strong>Chronic conditions:</strong> compare each eligible participant at their observed count and at one additional condition. Excluding the three participants already at the observed maximum of eight avoids extrapolating beyond the data and leaves 4,403 records.</li>
</ul>
<p>Here, <strong>standardization</strong> refers to averaging record-level predictions over the observed covariate distribution. Every predictor remains on its original scale.</p>
<p>The scenario definitions and averaging operation specify the target quantities: a response-scale difference and ratio. We next quantify their sampling uncertainty. Both combine <img src="https://latex.codecogs.com/png.latex?%5Cmu_i"> and <img src="https://latex.codecogs.com/png.latex?%5Cpi_i">, so their intervals must carry uncertainty in the two components, including their covariance, through the nonlinear expression <img src="https://latex.codecogs.com/png.latex?(1-%5Cpi_i)%5Cmu_i">.</p>
<p>We use a full-refit parametric bootstrap. Each replicate treats the fitted compact ZINB as a data-generating model and follows three steps:</p>
<ol type="1">
<li>simulate new visit counts at the observed covariate values,</li>
<li>refit both model components,</li>
<li>recalculate the same standardized differences and ratios.</li>
</ol>
<div class="callout callout-style-default callout-caution callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-11-contents" aria-controls="callout-11" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Caution</span>How the contrasts and intervals are constructed
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-11" class="callout-11-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>Let <img src="https://latex.codecogs.com/png.latex?%5Cmathcal%20I"> denote the records eligible for a contrast, and let <img src="https://latex.codecogs.com/png.latex?%5Cmathbf%7Bx%7D_i%5E%7B(0)%7D"> and <img src="https://latex.codecogs.com/png.latex?%5Cmathbf%7Bx%7D_i%5E%7B(1)%7D"> denote the reference and comparison versions of record <img src="https://latex.codecogs.com/png.latex?i">. For the fitted ZINB, the overall expected count under version <img src="https://latex.codecogs.com/png.latex?s"> is</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cwidehat%20m_i%5E%7B(s)%7D%0A=%20%5Cleft(1%20-%20%5Cwidehat%5Cpi_i%5E%7B(s)%7D%5Cright)%5Cwidehat%5Cmu_i%5E%7B(s)%7D.%0A"></p>
<p>Here, <img src="https://latex.codecogs.com/png.latex?s=0"> identifies the reference version and <img src="https://latex.codecogs.com/png.latex?s=1"> the comparison version.</p>
<p>Standardization averages these predictions over the eligible records:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Coverline%7B%5Cwidehat%20m%7D%5E%7B(s)%7D%0A=%20%5Cfrac%7B1%7D%7B%5Clvert%20%5Cmathcal%20I%20%5Crvert%7D%0A%5Csum_%7Bi%20%5Cin%20%5Cmathcal%20I%7D%20%5Cwidehat%20m_i%5E%7B(s)%7D.%0A"></p>
<p>The contrast is summarized as a difference and a ratio:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cwidehat%5CDelta%0A=%20%5Coverline%7B%5Cwidehat%20m%7D%5E%7B(1)%7D%20-%20%5Coverline%7B%5Cwidehat%20m%7D%5E%7B(0)%7D,%0A%5Cqquad%0A%5Cwidehat%20R%0A=%20%5Cfrac%7B%5Coverline%7B%5Cwidehat%20m%7D%5E%7B(1)%7D%7D%7B%5Coverline%7B%5Cwidehat%20m%7D%5E%7B(0)%7D%7D.%0A"></p>
<p>For each bootstrap replicate, we simulate new outcomes from the fitted ZINB, refit the same count and zero formulas, and recalculate <img src="https://latex.codecogs.com/png.latex?%5Cwidehat%5CDelta"> and <img src="https://latex.codecogs.com/png.latex?%5Cwidehat%20R">. The 2.5th and 97.5th percentiles of the replicated values form the approximate 95% percentile parametric-bootstrap confidence intervals.</p>
</div>
</div>
</div>
<p>This simulate–refit–recalculate cycle estimates sampling uncertainty in the complete standardized contrast. Table&nbsp;14 reports approximate 95% percentile intervals from 500 replicates.</p>
<div class="cell">
<details class="code-fold">
<summary>Show prediction-scenario and contrast code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb29" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb29-1">average_response_prediction <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(model, newdata) {</span>
<span id="cb29-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predict</span>(model, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">newdata =</span> newdata, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"response"</span>))</span>
<span id="cb29-3">}</span>
<span id="cb29-4"></span>
<span id="cb29-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># For chronic conditions, compare each eligible participant's observed count</span></span>
<span id="cb29-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># with that count plus one. Excluding the observed maximum avoids extrapolation.</span></span>
<span id="cb29-7">chronic_reference <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> medcare <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb29-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(numchron <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(numchron))</span>
<span id="cb29-9">chronic_comparison <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> chronic_reference <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb29-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">numchron =</span> numchron <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb29-11"></span>
<span id="cb29-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Binary contrasts compare two versions of every record while keeping the</span></span>
<span id="cb29-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># remaining observed predictors unchanged.</span></span>
<span id="cb29-14">female_scenario <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> medcare <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb29-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">male =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb29-16">male_scenario <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> medcare <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb29-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">male =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb29-18">not_married_scenario <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> medcare <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb29-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">married =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb29-20">married_scenario <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> medcare <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb29-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">married =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb29-22"></span>
<span id="cb29-23">estimate_response_contrasts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(model) {</span>
<span id="cb29-24">  tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb29-25">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Contrast_id =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"chronic"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sex"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"marriage"</span>),</span>
<span id="cb29-26">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Contrast =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb29-27">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Adding one chronic condition among participants with 0–7 conditions"</span>,</span>
<span id="cb29-28">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Male vs female"</span>,</span>
<span id="cb29-29">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Married vs not married"</span></span>
<span id="cb29-30">    ),</span>
<span id="cb29-31">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Reference =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb29-32">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">average_response_prediction</span>(model, chronic_reference),</span>
<span id="cb29-33">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">average_response_prediction</span>(model, female_scenario),</span>
<span id="cb29-34">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">average_response_prediction</span>(model, not_married_scenario)</span>
<span id="cb29-35">    ),</span>
<span id="cb29-36">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Comparison =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb29-37">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">average_response_prediction</span>(model, chronic_comparison),</span>
<span id="cb29-38">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">average_response_prediction</span>(model, male_scenario),</span>
<span id="cb29-39">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">average_response_prediction</span>(model, married_scenario)</span>
<span id="cb29-40">    )</span>
<span id="cb29-41">  ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb29-42">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(</span>
<span id="cb29-43">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Difference =</span> Comparison <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> Reference,</span>
<span id="cb29-44">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Ratio =</span> Comparison <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> Reference</span>
<span id="cb29-45">    )</span>
<span id="cb29-46">}</span>
<span id="cb29-47"></span>
<span id="cb29-48">overall_point_contrasts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">estimate_response_contrasts</span>(zinb_model)</span>
<span id="cb29-49"></span>
<span id="cb29-50"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># bootMer requires a numeric statistic. Stopping here records an unstable refit</span></span>
<span id="cb29-51"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># as a bootstrap failure rather than allowing it to enter the intervals.</span></span>
<span id="cb29-52">bootstrap_response_statistic <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(model) {</span>
<span id="cb29-53">  fit_is_stable <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span></span>
<span id="cb29-54">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">identical</span>(model<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>fit<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>convergence, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>L) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span></span>
<span id="cb29-55">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isTRUE</span>(model<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sdr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>pdHess)</span>
<span id="cb29-56"></span>
<span id="cb29-57">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>fit_is_stable) {</span>
<span id="cb29-58">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stop</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bootstrap refit failed the convergence or Hessian check."</span>)</span>
<span id="cb29-59">  }</span>
<span id="cb29-60"></span>
<span id="cb29-61">  contrasts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">estimate_response_contrasts</span>(model)</span>
<span id="cb29-62">  statistics <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(contrasts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Difference, contrasts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Ratio)</span>
<span id="cb29-63">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(statistics) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb29-64">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(contrasts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Contrast_id, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_difference"</span>),</span>
<span id="cb29-65">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(contrasts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Contrast_id, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_ratio"</span>)</span>
<span id="cb29-66">  )</span>
<span id="cb29-67">  statistics</span>
<span id="cb29-68">}</span></code></pre></div></div>
</details>
</div>
<div class="cell">
<details class="code-fold">
<summary>Show parametric-bootstrap refit code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb30" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb30-1">n_boot <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>L</span>
<span id="cb30-2">bootstrap_seed <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20260730</span>L</span>
<span id="cb30-3"></span>
<span id="cb30-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Leave one physical core free for Quarto and other desktop work. The fallback</span></span>
<span id="cb30-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># keeps the tutorial runnable when R cannot determine the physical core count.</span></span>
<span id="cb30-6">physical_cores <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> parallel<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">detectCores</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">logical =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb30-7">n_workers <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(physical_cores)) {</span>
<span id="cb30-8">  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>L</span>
<span id="cb30-9">} <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> {</span>
<span id="cb30-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>L, physical_cores <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>L)</span>
<span id="cb30-11">}</span>
<span id="cb30-12"></span>
<span id="cb30-13">run_bootstrap_refits <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>() {</span>
<span id="cb30-14">  bootstrap_cluster <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> parallel<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">makeCluster</span>(n_workers)</span>
<span id="cb30-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">on.exit</span>(parallel<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopCluster</span>(bootstrap_cluster), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">add =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb30-16"></span>
<span id="cb30-17">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Windows uses separate R sessions, so each worker needs the modelling</span></span>
<span id="cb30-18">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># packages and every object used when glmmTMB reconstructs the original fit.</span></span>
<span id="cb30-19">  parallel<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clusterEvalQ</span>(</span>
<span id="cb30-20">    bootstrap_cluster,</span>
<span id="cb30-21">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">suppressPackageStartupMessages</span>({</span>
<span id="cb30-22">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(lme4)</span>
<span id="cb30-23">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(glmmTMB)</span>
<span id="cb30-24">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span>
<span id="cb30-25">    })</span>
<span id="cb30-26">  )</span>
<span id="cb30-27"></span>
<span id="cb30-28">  parallel<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clusterExport</span>(</span>
<span id="cb30-29">    bootstrap_cluster,</span>
<span id="cb30-30">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb30-31">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"zinb_model"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"medcare"</span>,</span>
<span id="cb30-32">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"chronic_reference"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"chronic_comparison"</span>,</span>
<span id="cb30-33">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"female_scenario"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"male_scenario"</span>,</span>
<span id="cb30-34">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"not_married_scenario"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"married_scenario"</span>,</span>
<span id="cb30-35">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"average_response_prediction"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"estimate_response_contrasts"</span>,</span>
<span id="cb30-36">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bootstrap_response_statistic"</span></span>
<span id="cb30-37">    ),</span>
<span id="cb30-38">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">envir =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">environment</span>()</span>
<span id="cb30-39">  )</span>
<span id="cb30-40"></span>
<span id="cb30-41">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># bootMer simulates outcomes, refits the complete ZINB, and evaluates the six</span></span>
<span id="cb30-42">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># response-scale statistics for every replicate. Each refit uses one thread;</span></span>
<span id="cb30-43">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># independent replicates are distributed across the worker processes.</span></span>
<span id="cb30-44">  lme4<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bootMer</span>(</span>
<span id="cb30-45">    zinb_model,</span>
<span id="cb30-46">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">FUN =</span> bootstrap_response_statistic,</span>
<span id="cb30-47">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nsim =</span> n_boot,</span>
<span id="cb30-48">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">seed =</span> bootstrap_seed,</span>
<span id="cb30-49">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">use.u =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb30-50">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"parametric"</span>,</span>
<span id="cb30-51">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">parallel =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"snow"</span>,</span>
<span id="cb30-52">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ncpus =</span> n_workers,</span>
<span id="cb30-53">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cl =</span> bootstrap_cluster</span>
<span id="cb30-54">  )</span>
<span id="cb30-55">}</span>
<span id="cb30-56"></span>
<span id="cb30-57">bootstrap_result <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">run_bootstrap_refits</span>()</span>
<span id="cb30-58">bootstrap_succeeded <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">complete.cases</span>(bootstrap_result<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>t)</span>
<span id="cb30-59">n_boot_success <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(bootstrap_succeeded)</span>
<span id="cb30-60">n_boot_failed <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> n_boot <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> n_boot_success</span>
<span id="cb30-61">bootstrap_failure_messages <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">attr</span>(bootstrap_result, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"boot.fail.msgs"</span>)</span>
<span id="cb30-62"></span>
<span id="cb30-63"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># A high failure rate makes percentile intervals unreliable and signals a model</span></span>
<span id="cb30-64"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># stability problem that should be investigated rather than silently ignored.</span></span>
<span id="cb30-65"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (n_boot_success <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.95</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_boot) {</span>
<span id="cb30-66">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stop</span>(</span>
<span id="cb30-67">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fewer than 95% of parametric-bootstrap models converged with "</span>,</span>
<span id="cb30-68">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"a positive-definite Hessian."</span></span>
<span id="cb30-69">  )</span>
<span id="cb30-70">}</span>
<span id="cb30-71"></span>
<span id="cb30-72"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Cache only the raw successful statistics and diagnostics. Formatting remains</span></span>
<span id="cb30-73"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># in the lightweight table cell so prose or layout edits do not rerun refits.</span></span>
<span id="cb30-74">bootstrap_statistics <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> bootstrap_result<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>t[bootstrap_succeeded, , drop <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>]</span>
<span id="cb30-75"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rm</span>(bootstrap_result)</span></code></pre></div></div>
</details>
</div>
<div class="cell" data-tbl-colwidths="[40,13,13,18,16]">
<details class="code-fold">
<summary>Show interval-summary and table code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb31" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb31-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Convert the cached bootstrap matrix into percentile intervals. This cell is</span></span>
<span id="cb31-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># intentionally lightweight: labels, rounding, and layout can change freely.</span></span>
<span id="cb31-3">interval_endpoint <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(column, probability) {</span>
<span id="cb31-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(</span>
<span id="cb31-5">    bootstrap_statistics[, column],</span>
<span id="cb31-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">probs =</span> probability,</span>
<span id="cb31-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb31-8">  )</span>
<span id="cb31-9">}</span>
<span id="cb31-10"></span>
<span id="cb31-11">bootstrap_intervals <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> tibble<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(</span>
<span id="cb31-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Contrast_id =</span> overall_point_contrasts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Contrast_id,</span>
<span id="cb31-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Difference_low =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(</span>
<span id="cb31-14">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(Contrast_id, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_difference"</span>),</span>
<span id="cb31-15">    interval_endpoint,</span>
<span id="cb31-16">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb31-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">probability =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.025</span></span>
<span id="cb31-18">  ),</span>
<span id="cb31-19">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Difference_high =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(</span>
<span id="cb31-20">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(Contrast_id, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_difference"</span>),</span>
<span id="cb31-21">    interval_endpoint,</span>
<span id="cb31-22">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb31-23">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">probability =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.975</span></span>
<span id="cb31-24">  ),</span>
<span id="cb31-25">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Ratio_low =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(</span>
<span id="cb31-26">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(Contrast_id, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_ratio"</span>),</span>
<span id="cb31-27">    interval_endpoint,</span>
<span id="cb31-28">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb31-29">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">probability =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.025</span></span>
<span id="cb31-30">  ),</span>
<span id="cb31-31">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Ratio_high =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vapply</span>(</span>
<span id="cb31-32">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(Contrast_id, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_ratio"</span>),</span>
<span id="cb31-33">    interval_endpoint,</span>
<span id="cb31-34">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">numeric</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb31-35">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">probability =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.975</span></span>
<span id="cb31-36">  )</span>
<span id="cb31-37">)</span>
<span id="cb31-38"></span>
<span id="cb31-39">overall_contrasts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> overall_point_contrasts <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb31-40">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">left_join</span>(bootstrap_intervals, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Contrast_id"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb31-41">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transmute</span>(</span>
<span id="cb31-42">    Contrast,</span>
<span id="cb31-43">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Reference mean</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f"</span>, Reference),</span>
<span id="cb31-44">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Comparison mean</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f"</span>, Comparison),</span>
<span id="cb31-45">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Change (95% CI)</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(</span>
<span id="cb31-46">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%+.2f (%+.2f to %+.2f)"</span>,</span>
<span id="cb31-47">      Difference,</span>
<span id="cb31-48">      Difference_low,</span>
<span id="cb31-49">      Difference_high</span>
<span id="cb31-50">    ),</span>
<span id="cb31-51">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Ratio (95% CI)</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(</span>
<span id="cb31-52">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%.2f (%.2f–%.2f)"</span>,</span>
<span id="cb31-53">      Ratio,</span>
<span id="cb31-54">      Ratio_low,</span>
<span id="cb31-55">      Ratio_high</span>
<span id="cb31-56">    )</span>
<span id="cb31-57">  )</span>
<span id="cb31-58"></span>
<span id="cb31-59">knitr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kable</span>(</span>
<span id="cb31-60">  overall_contrasts,</span>
<span id="cb31-61">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">align =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"c"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"c"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"c"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>),</span>
<span id="cb31-62">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb31-63">)</span></code></pre></div></div>
</details>
<div id="tbl-zinb-overall-contrasts" class="cell quarto-float quarto-figure quarto-figure-center anchored" data-tbl-colwidths="[40,13,13,18,16]">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-zinb-overall-contrasts-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;14: Standardized contrasts in overall expected visits from the working ZINB model.
</figcaption>
<div aria-describedby="tbl-zinb-overall-contrasts-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output-display">
<table class="cell caption-top table table-sm table-striped small">
<colgroup>
<col style="width: 40%">
<col style="width: 13%">
<col style="width: 13%">
<col style="width: 18%">
<col style="width: 16%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: center;">Contrast</th>
<th style="text-align: center;">Reference mean</th>
<th style="text-align: center;">Comparison mean</th>
<th style="text-align: right;">Change (95% CI)</th>
<th style="text-align: right;">Ratio (95% CI)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">Adding one chronic condition among participants with 0–7 conditions</td>
<td style="text-align: center;">5.79</td>
<td style="text-align: center;">6.97</td>
<td style="text-align: right;">+1.18 (+1.02 to +1.36)</td>
<td style="text-align: right;">1.20 (1.18–1.23)</td>
</tr>
<tr class="even">
<td style="text-align: center;">Male vs female</td>
<td style="text-align: center;">5.96</td>
<td style="text-align: center;">5.50</td>
<td style="text-align: right;">-0.45 (-0.83 to -0.07)</td>
<td style="text-align: right;">0.92 (0.86–0.99)</td>
</tr>
<tr class="odd">
<td style="text-align: center;">Married vs not married</td>
<td style="text-align: center;">5.81</td>
<td style="text-align: center;">5.73</td>
<td style="text-align: right;">-0.09 (-0.49 to +0.29)</td>
<td style="text-align: right;">0.98 (0.92–1.05)</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</div>
<p>The chronic-condition contrast uses 4,403 participants; the binary contrasts use all 4,406. Parentheses contain approximate 95% percentile parametric-bootstrap confidence intervals.</p>
<p>Adding one chronic condition is associated with 1.18 more expected visits (95% CI 1.02 to 1.36), or a 20% increase. The count-state mean rises while the estimated extra-zero probability falls, so both pathways reinforce the response-scale increase.</p>
<p>Men have 0.45 fewer expected visits than women after standardization (95% CI 0.07 to 0.83 fewer), an estimated reduction of 8%. Both component point estimates act in the same direction: the count-component mean is slightly lower for men, while their higher estimated extra-zero probability supplies most of the overall difference.</p>
<p>Married participants have 0.09 fewer expected visits than participants who are not married, but the interval ranges from 0.49 fewer to 0.29 more visits. Here the pathways oppose one another: the fitted count-state mean is lower for married participants, while their lower estimated extra-zero probability raises the response-scale expectation. The near cancellation leaves no clear overall difference under this specification.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-12-contents" aria-controls="callout-12" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Why use a parametric bootstrap?
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-12" class="callout-12-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>A delta-method interval is a legitimate and much faster alternative. It approximates a nonlinear contrast with a straight line near the fitted coefficients and usually treats their joint sampling distribution as approximately normal. That approximation can work well, but our contrast averages a nonlinear combination of two fitted model components whose estimates can covary.</p>
<p>We chose the full-refit bootstrap because it carries that joint uncertainty through the complete calculation without first linearizing the contrast. Refitting also exposes simulated datasets in which the model cannot be estimated reliably. This choice is not universally superior: it costs more computation and still assumes that the fitted ZINB adequately represents the data-generating process. Readers who want to compare the delta method, coefficient simulation, and bootstrap approaches can consult the <a href="https://marginaleffects.com/chapters/uncertainty.html"><em>marginaleffects</em> guide to uncertainty</a>.</p>
</div>
</div>
</div>
<p>We use 500 replicates to keep the tutorial practical to reproduce. Substantive work should use more replicates when necessary and check that the interval endpoints are stable. The bootstrap used 5 local workers and successfully refitted 500 of 500 simulated datasets. The interval calculation excludes any refit that fails the convergence and Hessian checks used for the working model; none failed here.</p>
<p>The intervals condition on the observed covariates, the compact specification, and the fitted ZINB data-generating model. They exclude uncertainty from formula selection and residual misspecification, and they do not support a causal interpretation.</p>
<p>The three comparisons expose a general feature of zero-inflated regression: a predictor’s practical association emerges only after the count and zero pathways are recombined. Reinforcing pathways can magnify the response-scale association, while opposing pathways can nearly cancel even when both components appear meaningful. Standardized contrasts translate this latent two-process representation into the expected observed outcome that motivated the analysis.</p>
</section>
</section>
</section>
<section id="conclusion-and-final-remarks" class="level1" data-number="6">
<h1 data-number="6"><span class="header-section-number">6</span> Conclusion and Final Remarks</h1>
<p>In summary, we worked through a sequential modelling exercise that I hope resembles how you might approach a similar count dataset in practice. We began with Poisson to establish a baseline for the conditional mean, variation, and zero frequency. Its severe overdispersion and 37 expected zeros, against 683 observed, pointed towards a more flexible count distribution. When counts vary far more than Poisson allows, NB2 is often a good candidate to try next. Here, it accounted for about 91% of zeros (623) through a single count process.</p>
<p>With most of the apparent zero excess captured by NB2, the next question was whether adding a separate zero component improved this stronger baseline. We saw that adding a constant extra-zero component added very little. The substantial improvement appeared when that probability was allowed to vary across patient characteristics. Expanding the compact formula with three additional predictors provided no meaningful improvement after accounting for the extra complexity, so we retained the smaller specification as the more focused way to explore the two-process hypothesis.</p>
<p>For me one of the biggest takeaways for this tutorial should be that, when we are facing a dataset with a relatively high number of zeros in our response variable, we should start a sequence of progressive comparisons, beginning with the count distribution itself. Before adding a zero component, we should ask whether a count distribution with more realistic variation can already reproduce most of the excess zeros. Any remaining zero component then becomes a scientific hypothesis of its own, with predictors, assumptions, and diagnostic consequences. The compact ZINB gives that hypothesis an interpretable form for this tutorial, and what we gain is a clearer account of how two possible pathways may shape the observed outcome—and a clearer view of where that account remains incomplete.</p>
<section id="a-repeatable-workflow" class="level2" data-number="6.1">
<h2 data-number="6.1" class="anchored" data-anchor-id="a-repeatable-workflow"><span class="header-section-number">6.1</span> A Repeatable Workflow</h2>
<p>The approach we used for the Medicare data, and that I have used in practice, can be broken down and adapted to other count outcomes:</p>
<ol type="1">
<li><strong>Define the outcome and the processes that may generate it.</strong> Establish the observation window or exposure, decide what one count represents, and identify plausible reasons for both variation in the counts and the occurrence of zeros.</li>
<li><strong>Establish a count-family baseline.</strong> Begin with a simple count model, then use dispersion and residual checks to decide whether the count distribution needs more flexibility. A negative-binomial model is often a useful next candidate when Poisson variation is too restrictive.</li>
<li><strong>Test a basic extra-zero component.</strong> Within the selected count family, compare the ordinary model with a matched specification containing a constant extra-zero probability. This isolates whether a zero component adds enough to justify further development.</li>
<li><strong>Choose zero-component predictors deliberately.</strong> Use subject-matter knowledge and direct measures of the proposed zero-generating process whenever possible. When several formulas are plausible, compare a small candidate set with clear substantive interpretations.</li>
<li><strong>Check estimation stability.</strong> Confirm optimizer convergence, a positive-definite Hessian, finite standard errors, and the absence of extreme zero-component estimates before using fit statistics or residual diagnostics.</li>
<li><strong>Check the complete fitted distribution.</strong> Use simulation diagnostics to examine zero frequency, dispersion, overall distributional fit, residual patterns across important predictors, and observed versus predicted count frequencies. For predictive work, add repeated out-of-sample assessment with a distribution-sensitive score, such as held-out log predictive density or ranked probability score, alongside RMSE.</li>
<li><strong>Interpret the model in terms of the observed outcome.</strong> Explain the count and zero components separately, then recombine them on the response scale. Keep the interpretation conditional on the chosen specification, its remaining diagnostic departures, and the scientific meaning of the latent state.</li>
</ol>
</section>
<section id="choosing-an-appropriate-candidate" class="level2" data-number="6.2">
<h2 data-number="6.2" class="anchored" data-anchor-id="choosing-an-appropriate-candidate"><span class="header-section-number">6.2</span> Choosing an Appropriate Candidate</h2>
<p>Given the workflow, you can use the table below to form a candidate set, then use matched comparisons, estimation checks, and simulation diagnostics to decide which specifications remain defensible. Note that the table covers only the four model families discussed in this article; other count distributions and hurdle-type specifications may also be worth considering!</p>
<div id="tbl-model-choice" class="responsive hover quarto-float quarto-figure quarto-figure-center anchored" data-tbl-colwidths="20, 40, 40">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-model-choice-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;15: Screening guide for deciding which common count-model specifications merit fitting and diagnostic assessment. Final selection requires matched comparisons, stable estimation, and distributional checks.
</figcaption>
<div aria-describedby="tbl-model-choice-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="table-responsive">
<table class="table-hover caption-top table">
<colgroup>
<col style="width: 20%">
<col style="width: 40%">
<col style="width: 40%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">Model</th>
<th style="text-align: left;">Appropriate Candidate When</th>
<th style="text-align: left;">Reconsider When</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><strong>Poisson</strong></td>
<td style="text-align: left;">The conditional mean and variance are compatible (equidispersed), and simulations reproduce the zero frequency and tails</td>
<td style="text-align: left;">Residuals show overdispersion, underdispersion, a zero-frequency mismatch, or systematic patterns across predictors</td>
</tr>
<tr class="even">
<td style="text-align: left;"><strong>Negative binomial (NB2)</strong></td>
<td style="text-align: left;">Variation exceeds the Poisson assumption, and NB2 reproduces the residual spread, zero frequency, and tails without a separate zero component</td>
<td style="text-align: left;">Important zero-frequency, dispersion, tail, or predictor-specific departures remain</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><strong>Zero-inflated Poisson (ZIP)</strong></td>
<td style="text-align: left;">A separate extra-zero process has a defensible scientific interpretation, adding it improves distributional fit, and Poisson variation remains adequate within the count state</td>
<td style="text-align: left;">The count component remains overdispersed, the zero component is unstable, or its predictors lack a substantive interpretation</td>
</tr>
<tr class="even">
<td style="text-align: left;"><strong>Zero-inflated negative binomial (ZINB)</strong></td>
<td style="text-align: left;">NB2 variation is needed, and a substantively defensible zero component improves distributional fit beyond ordinary NB2</td>
<td style="text-align: left;">NB2 already reproduces the relevant features, zero-component estimates are unstable, or important residual departures remain</td>
</tr>
</tbody>
</table>
</div>
</div>
</figure>
</div>
</section>
<section id="sec-scope-reproducibility" class="level2" data-number="6.3">
<h2 data-number="6.3" class="anchored" data-anchor-id="sec-scope-reproducibility"><span class="header-section-number">6.3</span> Scope and Reproducibility</h2>
<p>These qualifications define the boundaries of the Medicare example. Age is recorded in decades: <code>6.6</code> represents 66 years, as confirmed by the fuller <a href="https://raw.githubusercontent.com/cran/AER/master/man/NMES1988.Rd"><code>AER::NMES1988</code> documentation</a>. The available data provide no participant-specific observation times, and the models include no exposure offset. We therefore treat each participant’s visit count as observed over the same one-year period, the <a href="https://meps.ahrq.gov/data_files/publications/rf9/rf9.shtml">1987 NMES observation year</a>, and compare counts under this common observation window.</p>
<p>Without the original survey-design variables, the estimates describe associations within the supplied sample under model-based uncertainty. They should not be interpreted as design-based population estimates for US Medicare beneficiaries.</p>
<div class="callout callout-style-simple callout-note callout-titled" title="Software used for this article">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-13-contents" aria-controls="callout-13" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Software used for this article
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-13" class="callout-13-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<ul>
<li><strong>Runtime:</strong> R 4.6.0 and Quarto 1.9.37</li>
<li><strong>Modelling and diagnostics:</strong> <code>glmmTMB</code> 1.1.14, DHARMa 0.5.0, <code>performance</code> 0.17.0, <code>parameters</code> 0.29.1, and <code>lme4</code> 2.0-1</li>
<li><strong>Data and output:</strong> <code>catdata</code> 1.2.5, <code>dplyr</code> 1.2.1, <code>ggplot2</code> 4.0.3, <code>gridExtra</code> 2.3, and <code>knitr</code> 1.51</li>
</ul>
</div>
</div>
</div>
</section>
<section id="further-reading" class="level2" data-number="6.4">
<h2 data-number="6.4" class="anchored" data-anchor-id="further-reading"><span class="header-section-number">6.4</span> Further Reading</h2>
<ul>
<li>For the Medicare example and its original economic application, Deb and Trivedi develop a finite-mixture analysis of healthcare use among older adults <span class="citation" data-cites="debtrivedi1997">(Deb and Trivedi 1997)</span>.</li>
<li>For model fitting, Brooks and colleagues explain <code>glmmTMB</code>’s parameterizations and its implementation of zero-inflated generalized linear models <span class="citation" data-cites="brooks2017">(Brooks et al. 2017)</span>.</li>
<li>For model checking, Hartig documents the simulation-based residuals and diagnostic tests provided by DHARMa <span class="citation" data-cites="hartig2026">(Hartig 2026)</span>.</li>
<li>For a broader practical guide in R, Zeileis, Kleiber, and Jackman compare Poisson, negative binomial, hurdle, and zero-inflated regression <span class="citation" data-cites="zeileis2008">(Zeileis et al. 2008)</span>.</li>
<li>For the methodological foundations, Lambert introduces zero-inflated Poisson regression, while Mullahy develops modified count models and hurdle-style formulations <span class="citation" data-cites="lambert1992 mullahy1986">(Lambert 1992; Mullahy 1986)</span>.</li>
</ul>
</section>
</section>
<section id="references" class="level1" data-number="7">
<h1 data-number="7"><span class="header-section-number">7</span> References</h1>
<div id="refs" class="references csl-bib-body hanging-indent">
<div id="ref-brooks2017" class="csl-entry">
Brooks, Mollie E., Kasper Kristensen, Koen J. van Benthem, et al. 2017. <span>“<span class="nocase">glmmTMB</span> Balances Speed and Flexibility Among Packages for Zero-Inflated Generalized Linear Mixed Modeling.”</span> <em>The R Journal</em> 9 (2): 378–400. <a href="https://doi.org/10.32614/RJ-2017-066">https://doi.org/10.32614/RJ-2017-066</a>.
</div>
<div id="ref-debtrivedi1997" class="csl-entry">
Deb, Partha, and Pravin K. Trivedi. 1997. <span>“Demand for Medical Care by the Elderly: A Finite Mixture Approach.”</span> <em>Journal of Applied Econometrics</em> 12 (3): 313–36. <a href="https://www.jstor.org/stable/2285252">https://www.jstor.org/stable/2285252</a>.
</div>
<div id="ref-dobson2018" class="csl-entry">
Dobson, Annette J., and Adrian G. Barnett. 2018. <em>An Introduction to Generalized Linear Models</em>. 4th ed. CRC Press.
</div>
<div id="ref-hartig2026" class="csl-entry">
Hartig, Florian. 2026. <em><span>DHARMa</span>: Residual Diagnostics for Hierarchical (Multi-Level/Mixed) Regression Models</em>. <a href="https://florianhartig.github.io/DHARMa/">https://florianhartig.github.io/DHARMa/</a>.
</div>
<div id="ref-lambert1992" class="csl-entry">
Lambert, Diane. 1992. <span>“Zero-Inflated Poisson Regression, with an Application to Defects in Manufacturing.”</span> <em>Technometrics</em> 34 (1): 1–14. <a href="https://doi.org/10.2307/1269547">https://doi.org/10.2307/1269547</a>.
</div>
<div id="ref-liu2019" class="csl-entry">
Liu, Lei, Ya Chen Tina Shih, Robert L. Strawderman, Daowen Zhang, Bankole A. Johnson, and Haitao Chai. 2019. <span>“Statistical Analysis of Zero-Inflated Nonnegative Continuous Data: A Review.”</span> <em>Statistical Science</em> 34 (2): 253–79. <a href="https://doi.org/10.1214/18-STS681">https://doi.org/10.1214/18-STS681</a>.
</div>
<div id="ref-mccullagh1989" class="csl-entry">
McCullagh, Peter, and John A. Nelder. 1989. <em>Generalized Linear Models</em>. 2nd ed. Chapman; Hall.
</div>
<div id="ref-mullahy1986" class="csl-entry">
Mullahy, John. 1986. <span>“Specification and Testing of Some Modified Count Data Models.”</span> <em>Journal of Econometrics</em> 33 (3): 341–65. <a href="https://doi.org/10.1016/0304-4076(86)90002-3">https://doi.org/10.1016/0304-4076(86)90002-3</a>.
</div>
<div id="ref-ospina2012" class="csl-entry">
Ospina, Raydonal, and Silvia L. P. Ferrari. 2012. <span>“A General Class of Zero-or-One Inflated Beta Regression Models.”</span> <em>Computational Statistics &amp; Data Analysis</em> 56 (6): 1609–23. <a href="https://doi.org/10.1016/j.csda.2011.10.005">https://doi.org/10.1016/j.csda.2011.10.005</a>.
</div>
<div id="ref-schauberger2025" class="csl-entry">
Schauberger, Gunther, and Gerhard Tutz. 2025. <em><span class="nocase">catdata</span>: Categorical Data</em>. <a href="https://CRAN.R-project.org/package=catdata">https://CRAN.R-project.org/package=catdata</a>.
</div>
<div id="ref-zeileis2008" class="csl-entry">
Zeileis, Achim, Christian Kleiber, and Simon Jackman. 2008. <span>“Regression Models for Count Data in <span>R</span>.”</span> <em>Journal of Statistical Software</em> 27 (8): 1–25. <a href="https://doi.org/10.18637/jss.v027.i08">https://doi.org/10.18637/jss.v027.i08</a>.
</div>
</div>


</section>

 ]]></description>
  <category>statistics</category>
  <category>modeling</category>
  <category>R</category>
  <category>tutorial</category>
  <guid>https://andreadifra.github.io/posts/zero-inflated-models-tutorial/</guid>
  <pubDate>Fri, 14 Aug 2026 00:00:00 GMT</pubDate>
  <media:content url="https://andreadifra.github.io/posts/zero-inflated-models-tutorial/figures/publication-image.png" medium="image" type="image/png" height="76" width="144"/>
</item>
<item>
  <title>Post With Code</title>
  <dc:creator>Harlow Malloc</dc:creator>
  <link>https://andreadifra.github.io/posts/post-with-code/</link>
  <description><![CDATA[ 






<p>This is a post with executable code.</p>



 ]]></description>
  <category>news</category>
  <category>code</category>
  <category>analysis</category>
  <guid>https://andreadifra.github.io/posts/post-with-code/</guid>
  <pubDate>Tue, 23 Jul 2024 00:00:00 GMT</pubDate>
  <media:content url="https://andreadifra.github.io/posts/post-with-code/image.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Welcome To My Blog</title>
  <dc:creator>Andrea Di Francia</dc:creator>
  <link>https://andreadifra.github.io/posts/welcome/</link>
  <description><![CDATA[ 






<p>Welcome — and thanks for stopping by.</p>
<p>This blog is where I share practical notes on data science, economics, and statistical modelling. My day-to-day work sits at the intersection of applied analytics, machine learning, and decision-focused communication, and this site gives me a place to turn that work into clear, reusable write-ups.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://andreadifra.github.io/posts/welcome/thumbnail.jpg" class="img-fluid figure-img"></p>
<figcaption>Welcome post thumbnail</figcaption>
</figure>
</div>
<p>You can expect a mix of:</p>
<ul>
<li>hands-on tutorials in R and Python</li>
<li>project notes on modelling, forecasting, and experimentation</li>
<li>lessons on making technical work useful for real decisions</li>
</ul>
<p>I am starting with a small set of pages, then expanding the site with deeper case studies and tutorials over time.</p>



 ]]></description>
  <category>news</category>
  <guid>https://andreadifra.github.io/posts/welcome/</guid>
  <pubDate>Sat, 20 Jul 2024 00:00:00 GMT</pubDate>
</item>
</channel>
</rss>
