Sample Size Calculation for Comparing Two Negative Binomial Rates

Negative Binomial Sample Size Calculator

Compare rates between two groups with overdispersed count data.

Expected events per unit of time/area.
Expected events in the intervention group.
k=0 is Poisson. Variance = μ + kμ²
80% 90% 95%
0.01 0.05 0.10
Ratio of group 2 size to group 1 size.

Required Sample Size

Group 1 (n1) 0
Group 2 (n2) 0
Total (N) 0

Understanding Negative Binomial Sample Size

In clinical trials and observational studies, researchers often count events over time (e.g., number of asthma exacerbations, frequency of hospital visits). While the Poisson distribution is the standard for count data, it assumes that the mean equals the variance. In real-world biological data, the variance is often larger than the mean—a phenomenon called overdispersion.

The Negative Binomial distribution accounts for this overdispersion by adding a parameter (k). This calculator uses the methodology derived from Zhu and Lakkis (2014) to determine the sample size required to compare two event rates while accounting for this extra variability.

Key Parameters

  • Rates (μ₁ & μ₂): The expected average number of events per person-time unit (e.g., events per year).
  • Dispersion Parameter (k): This defines the relationship between mean and variance. The variance is calculated as σ² = μ + kμ². As k approaches zero, the distribution becomes Poisson.
  • Power: The probability of correctly rejecting the null hypothesis when the treatment effect is real (usually 80% or 90%).
  • Alpha: The significance level, typically set at 0.05 for a two-sided test.

Example Calculation

"A researcher expects the control group to have 2.0 hospitalizations per year (μ₁) and the treatment group to have 1.4 (μ₂), representing a 30% reduction. Based on previous literature, the dispersion parameter is 0.6. Using 90% power and a 5% significance level with equal allocation (1:1), how many participants are needed?"

By entering these values into the calculator, you can determine the exact number of participants required to detect this difference with statistical confidence, preventing an underpowered study that might miss a clinically significant result.

function calculateNBSize() { var m1 = parseFloat(document.getElementById('rate1').value); var m2 = parseFloat(document.getElementById('rate2').value); var k = parseFloat(document.getElementById('dispersion').value); var pwr = parseFloat(document.getElementById('power').value); var alpha = parseFloat(document.getElementById('alpha').value); var r = parseFloat(document.getElementById('ratio').value); if (isNaN(m1) || isNaN(m2) || isNaN(k) || isNaN(r) || m1 <= 0 || m2 <= 0 || r <= 0) { alert("Please enter valid positive numbers for rates and allocation ratio."); return; } if (m1 === m2) { alert("Rates must be different to calculate a sample size."); return; } // Standard Normal Quantiles (approximate) var zAlpha = getZScore(1 – (alpha / 2)); var zBeta = getZScore(pwr); // Variance for Negative Binomial: Var = mu + k*mu^2 var v1 = m1 + (k * Math.pow(m1, 2)); var v2 = m2 + (k * Math.pow(m2, 2)); // Sample size formula for rates (Wald test based) // n1 = ( (z_a * sqrt(V0) + z_b * sqrt(V1))^2 ) / (delta^2) // Using the common approximation for Negative Binomial rate comparison: // n1 = ( (z_a + z_b)^2 * ( (m1 + k*m1^2) + (m2 + k*m2^2)/r ) ) / (m1 – m2)^2 var numerator = Math.pow((zAlpha + zBeta), 2) * (v1 + (v2 / r)); var denominator = Math.pow((m1 – m2), 2); var n1 = Math.ceil(numerator / denominator); var n2 = Math.ceil(n1 * r); var nTotal = n1 + n2; document.getElementById('n1-res').innerText = n1.toLocaleString(); document.getElementById('n2-res').innerText = n2.toLocaleString(); document.getElementById('ntotal-res').innerText = nTotal.toLocaleString(); document.getElementById('result-area').style.display = 'block'; // Smooth scroll to result document.getElementById('result-area').scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } function getZScore(p) { // Basic inverse normal CDF approximation var a1 = -39.6968302866538, a2 = 220.946098424521, a3 = -275.928510446969; var a4 = 138.357751867269, a5 = -30.6647980661472, a6 = 2.50662827745924; var b1 = -54.4760987942263, b2 = 161.585836858041, b3 = -155.698979859887; var b4 = 66.8013118877197, b5 = -13.2806815528857, c1 = -7.78489400243029E-03; var c2 = -0.322396458041136, c3 = -2.40075827716184, c4 = -2.54973253934373; var c5 = 4.37466414146497, c6 = 2.93816398269878, d1 = 7.78469570904146E-03; var d2 = 0.32246712907004, d3 = 2.44513413714299, d4 = 3.75440866190742; var p_low = 0.02425, p_high = 1 – p_low; var q, r; if (p < p_low) { q = Math.sqrt(-2 * Math.log(p)); return (((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) / ((((d1 * q + d2) * q + d3) * q + d4) * q + 1); } else if (p <= p_high) { q = p – 0.5; r = q * q; return (((((a1 * r + a2) * r + a3) * r + a4) * r + a5) * r + a6) * q / (((((b1 * r + b2) * r + b3) * r + b4) * r + b5) * r + 1); } else { q = Math.sqrt(-2 * Math.log(1 – p)); return -(((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) / ((((d1 * q + d2) * q + d3) * q + d4) * q + 1); } }

Leave a Comment