Model-Assisted Joint Analysis¶
Model-assisted joint analysis fits a nonparametric joint distribution over retained public and hidden cells, then uses posterior/bootstrap draws to rerun the audit. It complements adversarial Q-based ambiguity by summarizing outcomes under sampled cell laws.
Fit A Joint Distribution¶
import updatesupport as us
joint = us.fit_joint_distribution(
rows_or_frame,
public=["AGE_BAND", "EDU_BAND", "SEX"],
hidden=["AGE_BAND", "EDU_BAND", "SEX", "OCC_MAJOR", "WKHP_BAND", "RAC1P"],
target="income_over_threshold",
weight="sample_weight",
method="bayesian_bootstrap",
)
The fitted model stores retained hidden cells, their empirical joint
probabilities, and their hidden-cell target values. The default
method="bayesian_bootstrap" draws new cell masses from a Dirichlet distribution
centered on the empirical cell probabilities. Use method="empirical" when you
want deterministic draws equal to the fitted empirical joint law.
Use method="bootstrap" for an ordinary multinomial nonparametric bootstrap
over retained hidden cells.
You can inspect or reuse draws directly:
draw = joint.draw(seed=123)
records = draw.records()
The records are weighted hidden-cell rows with generated target and weight columns, so they can be fed back into the usual report helpers.
For update-support audits, the most direct draw is usually a hidden-composition draw:
draw = joint.hidden_composition_draw(seed=123)
That draw preserves the fitted public law and resamples hidden-cell shares
inside each public fiber. Plain joint.draw(...) samples the full joint law,
so public bucket masses can move too.
Posterior / Bootstrap Uncertainty Report¶
Use hidden_composition_uncertainty(...) when you want a standalone uncertainty
report over hidden composition:
uncertainty = us.hidden_composition_uncertainty(
rows_or_frame,
public=["AGE_BAND", "EDU_BAND", "SEX"],
hidden=["AGE_BAND", "EDU_BAND", "SEX", "OCC_MAJOR", "WKHP_BAND", "RAC1P"],
target="income_over_threshold",
weight="sample_weight",
method="bayesian_bootstrap",
draws=500,
seed=123,
q=us.q_tv_budget(0.10),
ambiguity_limit=0.015,
confidence_level=0.90,
)
print(uncertainty.to_markdown())
The report summarizes posterior/bootstrap uncertainty over:
the observed aggregate value under sampled hidden-cell masses,
lower and upper hidden-composition interval endpoints,
ambiguity width,
public adequacy rate,
claim failure rate against
ambiguity_limit.
By default, hidden_composition_uncertainty(...) uses
preserve_public_law=True. This keeps the public bucket distribution fixed and
resamples hidden composition within each public fiber. Set
preserve_public_law=False when you intentionally want full joint
public/hidden composition uncertainty.
It also emits structured tables:
uncertainty.to_tables()["metric_summaries"]
uncertainty.to_tables()["draws"]
uncertainty.to_tables()["joint_cells"]
Audit A Claim With Joint Draws¶
claim = us.claim(
estimate_name="Income-threshold target rate",
public=["AGE_BAND", "EDU_BAND", "SEX"],
hidden=["AGE_BAND", "EDU_BAND", "SEX", "OCC_MAJOR", "WKHP_BAND", "RAC1P"],
target="income_over_threshold",
weight="sample_weight",
q_presets=[us.q_tv_budget(0.10), us.q_chi_square_budget(0.25)],
candidate_refinements=["OCC_MAJOR", "WKHP_BAND", "RAC1P"],
ambiguity_limit=0.015,
)
verdict = us.audit_claim(
rows_or_frame,
claim,
joint_model=joint,
joint_draws=500,
joint_seed=123,
)
print(verdict.to_markdown())
The claim report adds a Model-Assisted Joint Analysis section with:
number of successful draws,
failure rate against the claim’s
ambiguity_limit,public adequacy rate,
ambiguity range and mean ambiguity across draws,
per-draw status rows.
If joint_model is omitted but joint_draws is positive, audit_claim(...)
fits the joint model from the same data using the claim’s public, hidden,
target, weight, and min_cell_weight settings.
Claim-level model-assisted analysis uses hidden-composition draws with the
public law preserved, matching the main reporting-stability question. Use the
standalone uncertainty report with preserve_public_law=False for monitoring
questions where future public bucket mix is also allowed to vary.
Interpretation¶
Read the outputs as three distinct layers:
Observed-support ambiguity: adversarial Q-based interval on the retained observed support.
Model-assisted hidden-composition draws: plausible within-public-fiber compositions according to the fitted nonparametric joint model.
Statistical uncertainty: external standard errors or intervals supplied by an upstream estimator.
The model-assisted layer introduces assumptions through the fitted joint cell law and the chosen effective sample size. It is useful for plausibility, future-composition stress tests, sparse-cell sensitivity, and monitoring, but it should not be described as a distribution-free robustness guarantee.