Skip to content

Harden joint g-computation target_pop path for forward-projection use#85

Merged
smjenness merged 2 commits into
mainfrom
fix/joint-target-pop-robustness
Jun 9, 2026
Merged

Harden joint g-computation target_pop path for forward-projection use#85
smjenness merged 2 commits into
mainfrom
fix/joint-target-pop-robustness

Conversation

@smjenness

Copy link
Copy Markdown
Contributor

Robustness fixes for the joint g-computation target_pop path, found while reviewing the ARTnet to ARTnetPredict forward-projection bridge. All changes are additive to the joint path. The legacy method = "existing" output is byte-identical to pre-refactor (backward-compat snapshot 3/3, R CMD check 0/0/0).

What changed

  • build_netstats(method = "joint", duration.method = "joint_lm") no longer crashes when a target_pop has an empty age stratum. The synth-duration aggregator now falls back to the within-ARTnet byage durations per empty stratum instead of passing NA into dissolution_coefs. A restricted-age population (common in forward-projected MSM data, e.g. dropping the 55-64 group) previously aborted the build.
  • target_pop data.frame degree/role/risk columns outside the fitted support are clamped with a warning, preserving the sum(nodefactor) = 2 * edges invariant. Out-of-support values (e.g. deg.casl = 4) previously broke it silently.
  • Nodefactor tabulations span the full level set via factor(), so an unobserved level (e.g. an absent risk quintile in a target_pop) no longer recycles a per-level vector. Byte-identical when all levels are present.
  • New optional seed argument to build_netstats for reproducibility of the stochastic sampling path. Defaults to NULL (no change in behavior).
  • Documented the joint target_pop semantics: supplied deg.main/deg.casl are covariates (degrees are re-predicted by g-computation, not transported as counts), and diag.status affects predicted degree, not just nodefactor_diag.status.
  • Fixed the stale scenario table in method_comparison.R / .md (it listed scenarios the harness no longer runs) and regenerated the report.
  • Added inst/validation/forward_projection_bridge_decision.md: a memo on the Option A vs B estimand decision for the ARTnetPredict bridge.

Validation

  • Backward-compat snapshot: ALL MATCH 3/3 for both default args and method = "existing" (tolerance 0).
  • Full testthat suite passes, including 15 new regression tests in tests/testthat/test-target-pop-robustness.R (crash, clamping, no-recycle, seed reproducibility).
  • R CMD check: 0 errors / 0 warnings / 0 notes.

Notes

  • Version bumped to 2.9.1 so downstream consumers (ARTnetPredict) can pin ARTnet >= 2.9.1. Drop that commit if you prefer a different versioning scheme.
  • Docs were regenerated with roxygen2 8.0.0 (the repo was last built with 7.3.3), which accounts for the DESCRIPTION roxygen-key and package-Rd churn.
  • Does not address the length-bias / truncation sampling concerns in Length-biased sampling and 5-partnership truncation bias in formation target stats #72; that remains open and orthogonal.

smjenness added 2 commits June 8, 2026 17:47
Fixes found while reviewing the ARTnet to ARTnetPredict bridge. All changes
are additive to the joint path; method = "existing" output is byte-identical
to pre-refactor (backward-compat snapshot 3/3, R CMD check 0/0/0).

- build_netstats(method = "joint", duration.method = "joint_lm") no longer
  crashes when a target_pop has an empty age stratum. The synth-duration
  aggregator now falls back to the within-ARTnet byage durations per empty
  stratum instead of passing NA into dissolution_coefs. A restricted-age
  population (common in forward-projected MSM data) previously aborted the
  build.
- target_pop data.frame degree/role/risk columns outside the fitted support
  are clamped with a warning, preserving the sum(nodefactor) == 2 * edges
  invariant. Out-of-support values previously broke it silently.
- nodefactor tabulations span the full level set via factor(), so an
  unobserved level (e.g. an absent risk quintile in a target_pop) no longer
  recycles a per-level vector. Byte-identical when all levels are present.
- New optional seed argument to build_netstats for reproducibility of the
  stochastic sampling path.
- Document the joint target_pop semantics: supplied deg.main/deg.casl are
  covariates (degrees are re-predicted by g-computation), and diag.status
  affects predicted degree, not just nodefactor_diag.status.
- Regression tests in tests/testthat/test-target-pop-robustness.R.
- Fix the stale scenario table in method_comparison.R / .md (it listed
  scenarios the harness no longer runs).
- Add inst/validation/forward_projection_bridge_decision.md: memo on the
  Option A vs B estimand decision for the ARTnetPredict bridge.

Docs regenerated with roxygen2 8.0.0 (DESCRIPTION roxygen key + package Rd).
Patch release for the joint g-computation target_pop robustness fixes, so
downstream consumers (ARTnetPredict) can pin ARTnet >= 2.9.1.
@smjenness smjenness merged commit a581773 into main Jun 9, 2026
1 check passed
@smjenness smjenness deleted the fix/joint-target-pop-robustness branch June 9, 2026 01:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant