Add zero-truncated gamma-Poisson functions#113
Open
sebdalgarno wants to merge 3 commits into
Open
Conversation
Adds log_lik_gamma_pois_zt(), dev_gamma_pois_zt(), ran_gamma_pois_zt(), and res_gamma_pois_zt() for the zero-truncated gamma-Poisson (negative binomial) distribution, mirroring the existing _zi family. The likelihood is the standard gamma-Poisson density divided by 1 - P(0; lambda, theta). Random samples use rejection sampling (zero draws are redrawn until accepted). Residuals centre on the truncated mean lambda / (1 - P(0)) and the standardised form scales by the truncated variance derived analytically. Deviances reuse the untruncated NB deviance approximation since the saturated MLE for the truncated likelihood has no closed form. Tests follow the patterns established for _zi and cover known values, NA handling, vectorisation, and the simulate workflow. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Match the brevity of the existing _zi family: keep titles, drop the multi-paragraph descriptions, keep at most a one-line context note where it adds something the title does not. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
There was a problem hiding this comment.
Pull request overview
Adds support for the zero-truncated gamma-Poisson (negative binomial) distribution to extras, mirroring the existing gamma-Poisson family helpers.
Changes:
- Added new
_ztfunctions:log_lik_gamma_pois_zt(),dev_gamma_pois_zt(),ran_gamma_pois_zt(),res_gamma_pois_zt(). - Added unit tests covering log-likelihood, deviance, random draws, and residual behavior for the new
_ztfamily. - Updated exports and regenerated documentation to include the new functions (plus a NEWS entry).
Reviewed changes
Copilot reviewed 57 out of 57 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| R/dev.R | Adds dev_gamma_pois_zt() implementation. |
| R/log-lik.R | Adds log_lik_gamma_pois_zt() implementation. |
| R/ran.R | Adds ran_gamma_pois_zt() via rejection sampling. |
| R/res.R | Adds res_gamma_pois_zt() with multiple residual types and simulation option. |
| NAMESPACE | Exports the new _zt functions. |
| NEWS.md | Adds a user-facing NEWS entry for the new functions. |
| tests/testthat/test-dev.R | Adds tests for _zt deviance and residual sign behavior. |
| tests/testthat/test-log-lik.R | Adds tests for _zt log-likelihood correctness and vectorization. |
| tests/testthat/test-ran.R | Adds tests for _zt sampling behavior and truncated mean. |
| tests/testthat/test-res.R | Adds tests for _zt residual types and simulated standardized residuals. |
| man/dev_gamma_pois_zi.Rd | Cross-links deviance docs to include dev_gamma_pois_zt(). |
| man/dev_gamma_pois_zt.Rd | New generated documentation for dev_gamma_pois_zt(). |
| man/log_lik_bern.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_beta.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_beta_binom.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_binom.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_exp.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_gamma.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_gamma_pois.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_gamma_pois_zi.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_gamma_pois_zt.Rd | New generated documentation for log_lik_gamma_pois_zt(). |
| man/log_lik_lnorm.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_neg_binom.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_norm.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_pois.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_pois_zi.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_skewnorm.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_student.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/log_lik_unif.Rd | Cross-links log-likelihood docs to include log_lik_gamma_pois_zt(). |
| man/ran_bern.Rd | Cross-links random-sampling docs to include ran_gamma_pois_zt(). |
| man/ran_beta_binom.Rd | Cross-links random-sampling docs to include ran_gamma_pois_zt(). |
| man/ran_binom.Rd | Cross-links random-sampling docs to include ran_gamma_pois_zt(). |
| man/ran_gamma.Rd | Cross-links random-sampling docs to include ran_gamma_pois_zt(). |
| man/ran_gamma_pois.Rd | Cross-links random-sampling docs to include ran_gamma_pois_zt(). |
| man/ran_gamma_pois_zi.Rd | Cross-links random-sampling docs to include ran_gamma_pois_zt(). |
| man/ran_gamma_pois_zt.Rd | New generated documentation for ran_gamma_pois_zt(). |
| man/ran_lnorm.Rd | Cross-links random-sampling docs to include ran_gamma_pois_zt(). |
| man/ran_neg_binom.Rd | Cross-links random-sampling docs to include ran_gamma_pois_zt(). |
| man/ran_norm.Rd | Cross-links random-sampling docs to include ran_gamma_pois_zt(). |
| man/ran_pois.Rd | Cross-links random-sampling docs to include ran_gamma_pois_zt(). |
| man/ran_pois_zi.Rd | Cross-links random-sampling docs to include ran_gamma_pois_zt(). |
| man/ran_skewnorm.Rd | Cross-links random-sampling docs to include ran_gamma_pois_zt(). |
| man/ran_student.Rd | Cross-links random-sampling docs to include ran_gamma_pois_zt(). |
| man/res_bern.Rd | Cross-links residual docs to include res_gamma_pois_zt(). |
| man/res_beta_binom.Rd | Cross-links residual docs to include res_gamma_pois_zt(). |
| man/res_binom.Rd | Cross-links residual docs to include res_gamma_pois_zt(). |
| man/res_gamma.Rd | Cross-links residual docs to include res_gamma_pois_zt(). |
| man/res_gamma_pois.Rd | Cross-links residual docs to include res_gamma_pois_zt(). |
| man/res_gamma_pois_zi.Rd | Cross-links residual docs to include res_gamma_pois_zt(). |
| man/res_gamma_pois_zt.Rd | New generated documentation for res_gamma_pois_zt(). |
| man/res_lnorm.Rd | Cross-links residual docs to include res_gamma_pois_zt(). |
| man/res_neg_binom.Rd | Cross-links residual docs to include res_gamma_pois_zt(). |
| man/res_norm.Rd | Cross-links residual docs to include res_gamma_pois_zt(). |
| man/res_pois.Rd | Cross-links residual docs to include res_gamma_pois_zt(). |
| man/res_pois_zi.Rd | Cross-links residual docs to include res_gamma_pois_zt(). |
| man/res_skewnorm.Rd | Cross-links residual docs to include res_gamma_pois_zt(). |
| man/res_student.Rd | Cross-links residual docs to include res_gamma_pois_zt(). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+117
to
+130
| lambda <- rep_len(lambda, n) | ||
| theta <- rep_len(theta, n) | ||
| out <- integer(n) | ||
| remaining <- seq_len(n) | ||
| while (length(remaining) > 0) { | ||
| draws <- as.integer(stats::rnbinom( | ||
| length(remaining), | ||
| mu = lambda[remaining], | ||
| size = 1 / theta[remaining] | ||
| )) | ||
| accepted <- draws > 0 | ||
| out[remaining[accepted]] <- draws[accepted] | ||
| remaining <- remaining[!accepted] | ||
| } |
Comment on lines
+127
to
+129
| accepted <- draws > 0 | ||
| out[remaining[accepted]] <- draws[accepted] | ||
| remaining <- remaining[!accepted] |
| log_lik_gamma_pois_zt <- function(x, lambda = 1, theta = 0) { | ||
| log_lik <- dnbinom(x, mu = lambda, size = 1 / theta, log = TRUE) | ||
| log_p0 <- dnbinom(0, mu = lambda, size = 1 / theta, log = TRUE) | ||
| log_lik - log1p(-exp(log_p0)) |
| log_lik_gamma_pois_zt <- function(x, lambda = 1, theta = 0) { | ||
| log_lik <- dnbinom(x, mu = lambda, size = 1 / theta, log = TRUE) | ||
| log_p0 <- dnbinom(0, mu = lambda, size = 1 / theta, log = TRUE) | ||
| log_lik - log1p(-exp(log_p0)) |
Comment on lines
+261
to
+268
| dev_gamma_pois_zt <- function(x, lambda = 1, theta = 0, res = FALSE) { | ||
| dev <- dev_gamma_pois(x, lambda = lambda, theta = theta, res = FALSE) | ||
| if (vld_false(res)) { | ||
| return(dev) | ||
| } | ||
| log_p0 <- dnbinom(0, mu = lambda, size = 1 / theta, log = TRUE) | ||
| trunc_mean <- lambda / -expm1(log_p0) | ||
| dev_res(x, trunc_mean, dev) |
| raw = x - trunc_mean, | ||
| standardized = (x - trunc_mean) / sqrt(trunc_var), | ||
| dev = dev_gamma_pois_zt(x, lambda = lambda, theta = theta, res = TRUE), | ||
| chk_subset(x, c("data", "raw", "dev", "standardized")) |
Comment on lines
+194
to
+201
| log_p0 <- dnbinom(0, mu = lambda, size = 1 / theta, log = TRUE) | ||
| one_minus_p0 <- -expm1(log_p0) | ||
| trunc_mean <- lambda / one_minus_p0 | ||
| trunc_var <- (lambda + lambda^2 * (1 + theta)) / one_minus_p0 - trunc_mean^2 | ||
| switch(type, | ||
| data = x, | ||
| raw = x - trunc_mean, | ||
| standardized = (x - trunc_mean) / sqrt(trunc_var), |
|
|
||
| # extras 0.8.0.9001 | ||
|
|
||
| - Added `log_lik_gamma_pois_zt()`, `dev_gamma_pois_zt()`, `ran_gamma_pois_zt()`, and `res_gamma_pois_zt()` for the zero-truncated gamma-Poisson (negative binomial) distribution. |
The previous deviance reused the untruncated NB approximation. Replace with per-observation numerical MLE via parallel_optimize, paralleling the beta-binomial pattern. Test values updated accordingly. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Member
Author
|
prrof from claude on why the MLE approach is better than previous approach: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
log_lik_gamma_pois_zt(),dev_gamma_pois_zt(),ran_gamma_pois_zt(), andres_gamma_pois_zt()for the zero-truncated gamma-Poisson (negative binomial) distribution, mirroring the existing_zifamily1 - P(0; lambda, theta)lambda / (1 - P(0)); standardised form scales by the analytically-derived truncated varianceWhy
Useful for fitting zero-truncated negative binomial models (e.g., count data filtered to be >= 1 by design) where current
extraslacks residual / random-draw / log-likelihood support. Encountered in a kelp biomass analysis where plant frond counts are filtered to fronds >= 1.Test plan
test-log-lik.R,test-dev.R,test-ran.R,test-res.Rfollowing_zipatternsdevtools::test(filter = "log-lik|dev|ran|res"))devtools::document())Y >= 1🤖 Generated with Claude Code