Representation adequacy and transport-stability auditing in Python
Project description
updatesupport
Audit whether the categories in your report are stable enough for the estimate you are reporting.
updatesupport quantifies hidden-composition ambiguity: how much an aggregate
rate, effect, or risk metric could move if the public buckets in a report stayed
fixed but the hidden mix inside those buckets changed.
It is useful when a dashboard, model-review pack, policy table, or causal analysis reports a number by coarse public categories and you need to know:
Are these categories enough to support this reported estimate?
Why It Exists
Many reports publish estimates by coarse buckets:
age band x education band x sex
product x region x FICO band x LTV band
segment x channel
Those buckets may hide subgroups with different target rates or effects. A
confidence interval answers sampling uncertainty. A model metric answers model
fit. updatesupport answers a different review question:
Holding the reported public mix fixed, how far could the aggregate move under plausible hidden subgroup shifts?
The output is a review-ready Markdown audit with:
- observed estimate
- hidden-composition stress interval
- transport ambiguity, the interval width
- public adequacy flag
- public cells driving the ambiguity
- refinement recommendations
- sensitivity checks
- public-representation frontier search for small stable reporting designs
This is not a replacement for causal identification, model validation, or sampling uncertainty. It is an audit layer for the reporting representation.
Quickstart
pip install updatesupport
or, in a uv project:
uv add updatesupport
import updatesupport as us
report = us.public_descent_report(
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",
candidate_refinements=["OCC_MAJOR", "WKHP_BAND", "RAC1P"],
min_cell_weight=25,
q="saturated",
title="Income-Threshold Representation Audit",
)
print(report.to_markdown())
The report asks:
If we only report by
AGE_BAND x EDU_BAND x SEX, how much could the aggregate income-threshold rate move if occupation, work hours, and race composition changed inside those public cells?
The stress interval is not a confidence interval. It is a partial-identification / sensitivity interval for hidden composition.
A Concrete Result
In the Folktables ACSIncome demo, the observed target rate is 12.37%. When the
public mix by age band, education band, and sex is held fixed, hidden subgroup
composition can move the target rate from:
11.79% to 13.44%
The transport ambiguity is 1.65 percentage points. In plain English:
The coarse public categories almost determine the aggregate income-threshold rate in this sample, but not quite. Hidden occupational and household differences still matter.
See the full analyst interpretation in docs/folktables-acs-income-interpretation.md.
Main Workflows
1. Audit a Public Report
Use public_descent_report(...) when you already know the public buckets,
hidden refinements, and target metric.
report = us.public_descent_report(
rows_or_frame,
public=["segment"],
hidden=["segment", "region", "tenure_band"],
target="outcome_rate",
candidate_refinements=["region", "tenure_band"],
q=us.q_bounded_shift(0.5),
)
2. Run Robustness Checks
Use sensitivity_report(...) when the conclusion should be checked across Q
presets, sparse-cell thresholds, or alternate hidden-state definitions.
sensitivity = us.sensitivity_report(
rows_or_frame,
public=["AGE_BAND", "SEX"],
hidden=["AGE_BAND", "SEX", "OCC_MAJOR", "WKHP_BAND"],
target="income_over_threshold",
min_cell_weights=[1, 10, 25],
q_presets=["saturated", us.q_bounded_shift(0.5), "observed"],
)
See docs/transport-presets.md for guidance on Q presets and docs/representation-adequacy.md for interpretation rules.
3. Choose a Stable Public Segmentation
Use public_representation_frontier(...) when you want the smallest public
bucket design that keeps ambiguity below a review threshold.
frontier = us.public_representation_frontier(
rows_or_frame,
base_public=["AGE_BAND", "EDU_BAND"],
hidden=["AGE_BAND", "EDU_BAND", "SEX", "OCC_MAJOR", "WKHP_BAND"],
target="income_over_threshold",
candidate_refinements=["SEX", "OCC_MAJOR", "WKHP_BAND"],
q_presets=["saturated", us.q_bounded_shift(0.5), "observed"],
min_cell_weights=[1, 10, 25],
ambiguity_limit=0.01,
bucket_budget=40,
search="beam",
)
explanation = frontier.explain_minimal_stable()
if explanation is not None:
print(explanation.to_markdown())
The frontier compares public-cell count, added public columns, and ambiguity across the stress grid. See docs/public-representation-frontier.md.
4. Audit Causal or Uplift Reports
Use a causal inference library such as EconML,
DoWhy,
DoubleML, or
CausalML to estimate effects
first. Then pass row-level or subgroup-level effects into updatesupport.
suite = us.causal_reporting_stability(
df,
public=["AGE_BAND", "SEX"],
hidden=["AGE_BAND", "SEX", "OCC_MAJOR", "WKHP_BAND", "RAC1P"],
effect="tau_hat",
weight="sample_weight",
candidate_refinements=["OCC_MAJOR", "WKHP_BAND", "RAC1P"],
q=us.q_bounded_shift(0.5),
statistical_estimate=ate_hat,
statistical_interval=(ci_low, ci_high),
statistical_method="causal estimator bootstrap",
)
This keeps four things separate: causal estimate, statistical uncertainty, hidden-composition ambiguity, and public refinement recommendations.
See docs/causal-library-integration.md.
5. Financial Model-Risk Plugin
Financial model-risk use cases live in the separate plugin package:
pip install "updatesupport[finance]"
# or
uv add "updatesupport[finance]"
It adds finance-oriented metrics such as expected loss and default rate without cluttering the core package.
See packages/updatesupport-finance/README.md.
Install Extras
pip install "updatesupport[cvxpy]" # TV, chi-square, KL, Wasserstein, custom CVXPY Q
pip install "updatesupport[examples]" # Folktables, pandas, plotting examples
pip install "updatesupport[causal]" # causal-effect examples
pip install "updatesupport[dowhy]" # CausalRefutation conversion
pip install "updatesupport[finance]" # financial model-risk plugin package
The same extras work with uv add:
uv add "updatesupport[cvxpy]"
uv add "updatesupport[examples]"
uv add "updatesupport[causal]"
uv add "updatesupport[dowhy]"
uv add "updatesupport[finance]"
The causal docs cover EconML, DoWhy, DoubleML, and CausalML handoffs.
For all examples and optional integrations:
pip install "updatesupport[examples,causal,dowhy,cvxpy,finance]"
# or
uv add "updatesupport[examples,causal,dowhy,cvxpy,finance]"
Examples
Run the no-download Folktables smoke demo from a source checkout:
uv run python examples/folktables_acs.py --synthetic
Run the real Folktables ACSIncome example:
uv run --extra examples python examples/folktables_acs.py \
--task income \
--states CA \
--year 2018 \
--sample 50000 \
--min-cell-weight 25
Generate the benchmark gallery:
uv run --extra examples --extra causal python examples/benchmark_gallery.py
Run the finance plugin example:
uv run --package updatesupport-finance python \
packages/updatesupport-finance/examples/model_risk_portfolio.py
See docs/benchmark-gallery.md for reproducible case studies.
Source Development
git clone https://github.com/nahuaque/updatesupport.git
cd updatesupport
uv sync --all-packages --group dev --extra cvxpy --extra examples
uv run pytest
Documentation
- Representation adequacy guide
- Public representation frontier
- Transport preset guide
- Using
updatesupportwith causal inference libraries - Benchmark gallery
- Theory and backend reference
- Extension and plugin architecture
- Release guide
- Folktables ACSIncome result interpretation
- Update-Relevant Support: Hume's Missing Descent
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file updatesupport-0.1.1.tar.gz.
File metadata
- Download URL: updatesupport-0.1.1.tar.gz
- Upload date:
- Size: 309.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9f59d741f50dc6502a7fde5604eb1aa00a4aa991fbda26f26a16eda5c2bc2831
|
|
| MD5 |
6c9d674a24ab33d0514dadc68b901e56
|
|
| BLAKE2b-256 |
be92fd5c203a03a62a5eef151c44a21ca355d6303febc82c9f40ec0a7f60ce62
|
File details
Details for the file updatesupport-0.1.1-py3-none-any.whl.
File metadata
- Download URL: updatesupport-0.1.1-py3-none-any.whl
- Upload date:
- Size: 66.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3292114faf6466b5ce2538023f76504bda8bd6f4b00b01300c05a99b7c0a7a01
|
|
| MD5 |
7d08bf5e2f7c5b5bb3b0f48c1b0c6fdb
|
|
| BLAKE2b-256 |
a8b736d3d892df6f5f84120cee95072bedcdeb9a07a8c4bc8620e01cad38c054
|