Metadata-Version: 2.3
Name: health-code
Version: 0.1.9
Summary: print_unique and an editable national mortality disclosure script.
Requires-Dist: polars>=1.36.1,<1.42
Requires-Dist: xlsxwriter>=3.0.9,<4
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# health-code

One editable Python script that prepares the national mortality table for Census disclosure review, plus a small `print_unique` helper.

```bash
uv pip install --upgrade health-code
health-example national_mortality_disclosure.py
```

Edit the settings at the top of the copied script (input and output folders, `REQUEST_DATE`, and the placeholder column names), then run it with `uv run python national_mortality_disclosure.py`.

## Input

One parquet file per year, `mortality_{year}.parquet` for 2001-2024, with one row per year × sex × age × income percentile (`income_percentile` runs from 0 to 100):

- `deaths` and `n`: unweighted counts;
- `n_weighted`: the sum of weights;
- `mortality_rate_reweighted`: the unrounded, unsmoothed weighted death rate (0-1), whose denominator is `n_weighted`.

The script computes `survivors = n - deaths` and weighted deaths, `deaths_reweighted = mortality_rate_reweighted * n_weighted`.

## What it does

1. **Ventile rule.** Within each year, sex and age, the lowest non-empty percentile is the pooled bottom bin and is never switched. The other percentiles form ventiles 1-5, 6-10, ..., 96-100; percentiles that share a ventile with the bottom bin form a smaller group of their own. A percentile cell fails if its exact `n`, deaths or survivors is below 15; an empty cell (`n == 0`) also fails. If any cell in a group fails, every row in the group shows the group's values, repeated, and is marked `aggregation_level = "ventile"`. Group values are sums of `n`, deaths, `n_weighted` and weighted deaths, with survivors and the weighted rate recalculated from the sums. Otherwise rows keep their own values and are marked `"percentile"`.
2. **Suppression**, using the exact values after step 1: `n` shows `<15` and `n_weighted` shows `D` when `n` is below 15. The weighted rate and weighted deaths show `D` when `n`, deaths or survivors is below 15. A group that still fails stays suppressed on all its rows.
3. **Rounding.** `n` is rounded to the nearest 10, 50, 100, 500 or 1,000 depending on its size (ties to even), or to four significant digits from a million up. Weighted numbers are rounded to four significant digits.
4. Empty cells are not written.

## Output

```text
YYYYMMDD/
  support/national_mortality_YYYYMMDD_support_T13T26.xlsx
  for_release/national_mortality_YYYYMMDD_T13T26.xlsx
```

- Each workbook's first sheet, `CUI`, holds only the Census CUI header. The data are on the sheet `national_mortality` (release) or `national_mortality_support` (support).
- **Release:** `year, sex, income_percentile, age, aggregation_level, mortality_rate_reweighted, deaths_reweighted, n, n_weighted`. Unweighted deaths, survivors and the unweighted rate are not released.
- **Support:** the same rows in the same order, with the exact `n, deaths, survivors, n_weighted, deaths_reweighted, mortality_rate_reweighted`.

The script also prints the share of rows showing ventile values and the share with a suppressed rate, overall and by sex and age band, and the number of released estimates (each ventile group's repeated values counted once), and the sample size for the request README: total n in person-years, and the lowest and highest number of people in a year. Rerunning replaces the two files. In the release workbook, rounded numbers are stored as numbers; `<15` and `D` are stored as text.

Rounding follows the [FSRDC Disclosure Avoidance Methods Handbook](https://www2.census.gov/adrm/FSRDC/Resources/FSRDC-Disclosure-Avoidance-Methods-Handbook.pdf), pp. 27-29. Census disclosure review still applies.

## print_unique

```python
from health import print_unique
print_unique(df, "year")
```

## Versions

- 0.1.9: prints the sample size (total person-years and people per year).
- 0.1.8: percentiles run to 100. The bottom bin is the lowest non-empty percentile in each year, sex and age instead of a fixed cutoff, and the other groups are ventiles 1-5, ..., 96-100.
- 0.1.7: writes Excel workbooks with a CUI cover sheet instead of CSVs.
- 0.1.6: one script, `national_mortality_disclosure.py`. It applies the ventile rule and releases the weighted rate, weighted deaths, weighted n and rounded unweighted n. The older `prepare_mortality_disclosure.py` and `check_suppression.py` were removed.
- 0.1.5: added a suppression check. 0.1.4: weighted mortality and weighted deaths. 0.1.3: unweighted mortality from counts. 0.1.2: one straight-line script instead of a helper API.
