diff --git a/changelog.d/297-cps-educational-attainment.added.md b/changelog.d/297-cps-educational-attainment.added.md new file mode 100644 index 0000000000..35aa138698 --- /dev/null +++ b/changelog.d/297-cps-educational-attainment.added.md @@ -0,0 +1,9 @@ +The US fiscal-refresh build can carry educational attainment as an auxiliary person column, `cps_educational_attainment`, beside the raw Census `A_HGA` it is classified from (microcosm#297; the student debt pilot, Project 2). `--cps-educational-attainment` joins each person to the pinned official CPS ASEC person member on (income year, `PERIDNUM`), checks the Census household, person and age identity, and never predicts or defaults a value; a support clone takes its source person's code. `--asec-attainment-source INCOME_YEAR=PATH` supplies local archives, and unmapped years are fetched and verified against the same pins. + +The classes are the seven ACS S1501 population-25-and-over categories (less than 9th grade; 9th to 12th grade, no diploma; high school graduate or equivalency; some college, no degree; associate's, occupational and academic together; bachelor's; graduate or professional), plus `not_in_universe` under 15. The ACS PUMS `SCHL` map is defined and tested; the ACS-local lane does not read `SCHL` yet, and the stage refuses ACS-spine rows. The degree-ROI classes are `associates_degree` (two-year) and `bachelors_degree` (four-year) against the high-school baseline. + +Provenance. `microcosm.data.stored_inputs.US_AUXILIARY_STORED_COLUMNS` flags the column as auxiliary (carried for conditioning and calibration, not consumed by rules) and joins the stored-input register. + +Targets. The US target compiler binds ACS 1-year S1501 state cells for the population 25 and over (one per state and class) as person counts of the column (family `census_educational_attainment`, materializer `population_attainment`), and leaves the universe totals, the 18-to-24 universe and Puerto Rico unbound. The fiscal-refresh materializer counts them, and a frame without the column refuses rather than binding zeros. The pinned Chronicle feed carries no S1501 facts, so no release binds them until PolicyEngine/chronicle#347 merges and the US feed is re-pinned. + +The receipt is `experiments/297-cps-educational-attainment-receipt.md`, run on Modal with `experiments/modal_297.py`. diff --git a/docs/us-fact-to-target.md b/docs/us-fact-to-target.md index e4ae417a8d..11cb93fb5c 100644 --- a/docs/us-fact-to-target.md +++ b/docs/us-fact-to-target.md @@ -186,6 +186,52 @@ binds them: band. `experiments/940-state-agi-bands/` measures pre-calibration support per state and band on the #982 fix's offline outputs. +### ACS S1501 state attainment cells bind on an auxiliary column (microcosm#297) + +ACS population margins are raw survey quantities, so the doctrine above +admits them. The compiler still admits `census_acs` only at +congressional-district geography, with one exception: +`_acs_attainment_reference_from_fact` binds the ACS 1-year S1501 state +attainment record sets +(`census_acs.acs1_.s1501.state_attainment_25_plus.`, Chronicle +package `census/acs_s1501_state_2024`). + +- **Which rows.** The population-25-and-over detail rows, one per state and + class, for the 50 states and DC. The universe totals stay unbound, because + Census PEP binds population by state and age. The 18-to-24 universe stays + unbound too: the ACS counts dormitory residents in the state of their + college, and the CPS counts them in their parents' household. Puerto Rico + is outside the model. A detail row whose category, age band or measure is + not the reviewed one raises. +- **The column.** Each row counts persons in its age band whose auxiliary + `cps_educational_attainment` class is the row's + (`microcosm.build.us_runtime.educational_attainment`; family + `census_educational_attainment`, materializer `population_attainment`). + The fiscal-refresh build writes the column with + `--cps-educational-attainment`. A frame without it refuses to materialize + the rows. The rows of one state differ only in their class, so the + congressional-district reconciliation rule in `fiscal_target_references.json` + matches on `educational_attainment_category` too. +- **Levels.** The rows bind as levels. ACS 1-year weights are controlled to + the Census population estimates, so their 25-and-over totals sit close to + the PEP totals the release already binds. The receipt measures the gap per + state (`experiments/297-cps-educational-attainment-receipt.md`). If it + grows, rebase the rows onto the bound state population, as the AGI bands + are. +- **Before they bind.** The CPS and the ACS split some college from + associate's degrees differently: on the published default the release + has fewer people with some college and more with an associate's degree + than S1501 in almost every state, and their sum is off by less than the + some-college cell alone. Binding the two cells separately would move weight + to settle a definition. The + `less_than_9th_grade` cells are also thin in small states. The receipt + measures both; the re-pin review decides whether to bind the seven cells + or merged ones. +- **Feed.** The pinned feed carries no S1501 facts. When the re-pinned feed + adds them, regenerate the parity manifest, which then declares + `census_acs.acs1_2024` compiled. A release that compiles them must also + run with `--cps-educational-attainment`. + ## 4. Keep the exclusion register honest `US_FISCAL_TARGET_SUPPORT_EXCLUSIONS` is keyed by `source_record_id` and its diff --git a/experiments/297-cps-educational-attainment-receipt.md b/experiments/297-cps-educational-attainment-receipt.md new file mode 100644 index 0000000000..7b7e22e856 --- /dev/null +++ b/experiments/297-cps-educational-attainment-receipt.md @@ -0,0 +1,103 @@ +# microcosm#297 receipt: CPS educational attainment against ACS S1501 + +Generated 2026-10-22 by `experiments/build_297_attainment_receipt.py` at commit `e2621e231c6cbc62939711e7c967be314624f65c`, Modal run `20261022T171517Z-e2621e231` (`experiments/modal_297.py`). Machine-readable copy: `experiments/receipts/297-cps-educational-attainment-s1501.json`. + +The build stage ran on the published release `populace-us-2024-spm-20260915` (166,321 persons, 57,240 households) at its calibrated weights. Every person joined its own Census member row; the signal gate passed. The S1501 facts are a **temporary draft input** (PolicyEngine/chronicle#347, unmerged): 676 facts, 357 compiled targets (51 states and DC x 7 classes, population 25 and over), 0 mismatches against the raw Census response, largest gap between a state's categories and its total 0. + +## Classes + +| Class | CPS ASEC `A_HGA` | ACS PUMS `SCHL` | Six-class view | +|---|---|---|---| +| `less_than_9th_grade` | 31-34 | 01-11 | less than high school | +| `9th_to_12th_grade_no_diploma` | 35-38 | 12-15 | less than high school | +| `high_school_graduate_includes_equivalency` | 39 | 16, 17 | high school or GED | +| `some_college_no_degree` | 40 | 18, 19 | some college, no degree | +| `associates_degree` | 41, 42 | 20 | associate's | +| `bachelors_degree` | 43 | 21 | bachelor's | +| `graduate_or_professional_degree` | 44, 45, 46 | 22, 23, 24 | graduate or professional | +| `not_in_universe` | 0 (Children) | blank, or under 15 | | + +## National, population 25 and over (sum of the 51 state cells) + +| Class | S1501 | Release | S1501 share | Release share | +|---|---:|---:|---:|---:| +| < 9th grade | 10.91M | 7.82M | 4.6% | 3.3% | +| 9th-12th, no diploma | 12.87M | 11.70M | 5.5% | 5.0% | +| High school or GED | 60.70M | 65.69M | 25.7% | 27.9% | +| Some college, no degree | 43.65M | 33.29M | 18.5% | 14.1% | +| Associate's | 20.85M | 26.24M | 8.8% | 11.1% | +| Bachelor's | 52.23M | 57.04M | 22.1% | 24.2% | +| Graduate or professional | 34.70M | 33.79M | 14.7% | 14.3% | + +## State cells (357) + +| Measure | Value | +|---|---:| +| Mean abs share error | 2.29 pp | +| 90th percentile abs share error | 5.21 pp | +| Max abs share error | 10.84 pp | +| Median abs level error | 15.3% | +| 90th percentile abs level error | 46.3% | +| Max abs level error | 83.3% | +| Fewest records in a cell | 4 | +| Fewest households in a cell | 3 | +| S1501 25+ total vs release 25+ population, median abs | 0.14% | +| S1501 25+ total vs release 25+ population, max abs | 3.94% | + +Share error is the release's share of a state's population 25 and over in a class minus S1501's; level error compares counts. + +### Classes the degree-ROI analysis uses + +Two-year degree = `associates_degree`, four-year degree = `bachelors_degree`, each against the `high_school_graduate_includes_equivalency` baseline. + +| Role | Class | Mean abs share error | Max abs share error | Median abs level error | Fewest records | +|---|---|---:|---:|---:|---:| +| baseline | `high_school_graduate_includes_equivalency` | 2.87 pp | 10.84 pp | 8.5% | 95 | +| two_year_degree | `associates_degree` | 2.45 pp | 7.29 pp | 19.2% | 21 | +| four_year_degree | `bachelors_degree` | 2.32 pp | 8.11 pp | 8.7% | 221 | + +### Largest share errors + +| State | Class | S1501 share | Release share | Error | Records | +|---|---|---:|---:|---:|---:| +| MS | High school or GED | 29.4% | 40.2% | +10.84 pp | 527 | +| MN | Some college, no degree | 19.2% | 9.3% | -9.88 pp | 230 | +| HI | Some college, no degree | 18.6% | 8.8% | -9.82 pp | 240 | +| MT | Some college, no degree | 22.7% | 13.3% | -9.41 pp | 218 | +| AK | High school or GED | 28.5% | 36.8% | +8.32 pp | 464 | +| ND | Some college, no degree | 21.7% | 13.4% | -8.31 pp | 178 | +| VA | Bachelor's | 24.1% | 32.2% | +8.11 pp | 718 | +| MD | Bachelor's | 23.2% | 31.0% | +7.86 pp | 545 | +| GA | Some college, no degree | 18.8% | 11.0% | -7.86 pp | 276 | +| ME | High school or GED | 29.5% | 37.0% | +7.50 pp | 471 | + +### Reading the comparison + +- **Some college against associate's is an instrument difference.** Nationally the release has 14.1% some college, no degree against S1501's 18.5%, and 11.1% associate's against 8.8%. The release is below S1501 on some college in 49 of 51 states and above it on associate's in 44. The gap has one sign almost everywhere, so it reads as a difference between the instruments rather than sampling: the CPS interviews by telephone or visit and offers occupational and academic associate's answers, the ACS is mostly self-response and includes group quarters (Census, "Educational Attainment Fact Sheet", https://www.census.gov/topics/education/educational-attainment/guidance/factsheet-acs-cps.html). Binding the two cells separately would move weight to settle a definition. Their sum is -2.1 pp off nationally (25.3% against 27.3%), less than the some-college cell alone; the merged rows below give the state spread. +- **Thin cells.** 13 cells have fewer than 30 records; 10 of them are `less_than_9th_grade`. The standalone calibration's largest weight ratio (131) is in LA. Merging the two classes below a diploma (the six-class view) thickens those cells. + +| Merged row | Mean abs share error | Max abs share error | +|---|---:|---:| +| less_than_high_school | 1.73 pp | 6.44 pp | +| some_college_or_associates | 2.93 pp | 7.45 pp | + +## Held out: population 18 to 24 + +Not compiled: the ACS counts college students in dormitories (group quarters) in the state of their college, the CPS in their parents' household. +Mean abs share error 6.81 pp, max 34.03 pp; mean signed error by category: less_than_high_school_graduate +2.43 pp, high_school_graduate_includes_equivalency -3.96 pp, some_college_or_associates_degree +2.82 pp, bachelors_degree_or_higher -1.28 pp. + +## Standalone calibration to the cells + +Per-state minimum-KL reweighting of the release's household weights to the seven 25+ cells, holding the state's population under 25 fixed. Not the release solve, which fits every target jointly; it shows what binding these cells alone asks of the weights. + +| Measure | Value | +|---|---:| +| Max abs level error after | 0.0000% | +| Weight ratio, lowest state 1st percentile | 0.380 | +| Weight ratio, highest state 99th percentile | 5.944 | +| Weight ratio, min / max | 0.176 / 130.971 | +| Kish effective sample size kept, lowest state | 82.6% | + +## SCF education-debt imputation (microcosm#1073, PR #1246) + +The #1073 hold-out already measured SCF `educ` as a predictor: `build_plus_education` raised the household rank correlation (0.168 to 0.207) but moved the share with debt from -0.30 pp to -0.92 pp. With this column the host side of that predictor exists: map SCF `educ` (reference person) and the host reference person's `cps_educational_attainment` to the same seven classes, and condition the QRFs on it. The share error suggests adding it with the share calibrated to FSA borrower counts (microcosm#1074) rather than as a bare predictor. Nothing here changes #1246. diff --git a/experiments/build_297_attainment_receipt.py b/experiments/build_297_attainment_receipt.py new file mode 100644 index 0000000000..9426724a86 --- /dev/null +++ b/experiments/build_297_attainment_receipt.py @@ -0,0 +1,756 @@ +"""Receipt for microcosm#297: CPS educational attainment against ACS S1501. + +Runs the build's attainment stage on a published US release, compiles the ACS +2024 1-year S1501 state attainment facts through the US target compiler, and +materializes every compiled target with the fiscal-refresh tool's own +materializer. It writes: + +- ``experiments/receipts/297-cps-educational-attainment-s1501.json``: every + compiled cell's S1501 value, the release's weighted count, the support + (records and households carrying the cell) and a standalone per-state + entropy calibration of the release's household weights to the cells; +- ``experiments/297-cps-educational-attainment-receipt.md``: the summary; +- ``/populace_us_2024_cps_educational_attainment.csv.gz``: + ``person_id``, ``A_HGA`` and ``cps_educational_attainment`` for every person + of the release, so an analysis can join the column now. The sidecar is build + evidence, not a release, and is not committed. + +The S1501 facts are a TEMPORARY draft input (PolicyEngine/chronicle#347, +unmerged); ``--s1501-raw`` is the Census response that package pins, and every +compiled value is checked against it. Nothing here publishes, stages or +certifies anything. + + python experiments/build_297_attainment_receipt.py --h5 populace_us_2024.h5 \\ + --asec-archive 2022=asecpub23csv.zip --asec-archive 2023=asecpub24csv.zip \\ + --asec-archive 2024=asecpub25csv.zip --s1501-facts consumer_facts.jsonl \\ + --s1501-raw acs_S1501_state_2024.json --sidecar-dir out --run +""" + +from __future__ import annotations + +import argparse +import hashlib +import importlib.util +import json +import subprocess +from datetime import UTC, datetime +from pathlib import Path + +import numpy as np +import pandas as pd + +from microcosm.build.ledger_targets import compile_ledger_target_references +from microcosm.build.us_runtime import educational_attainment as ea +from microcosm.build.us_runtime import fiscal_targets +from microcosm.calibrate.geography_constants import US_STATE_FIPS_TO_POSTAL +from microcosm.frame import Frame, WeightKind, Weights +from microcosm.frame.units import US_SCHEMA + +REPO = Path(__file__).resolve().parents[1] +RECEIPT_JSON = ( + REPO / "experiments" / "receipts" / "297-cps-educational-attainment-s1501.json" +) +RECEIPT_MD = REPO / "experiments" / "297-cps-educational-attainment-receipt.md" +HOST_RELEASE = "populace-us-2024-spm-20260915" +TARGET_PERIOD = 2024 +#: S1501_C01 estimate ids of the population-25-and-over rows, by category. +S1501_25_PLUS_COLUMNS = { + "all": "S1501_C01_006E", + ea.LESS_THAN_9TH_GRADE: "S1501_C01_007E", + ea.GRADE_9_TO_12_NO_DIPLOMA: "S1501_C01_008E", + ea.HIGH_SCHOOL_GRADUATE: "S1501_C01_009E", + ea.SOME_COLLEGE_NO_DEGREE: "S1501_C01_010E", + ea.ASSOCIATES_DEGREE: "S1501_C01_011E", + ea.BACHELORS_DEGREE: "S1501_C01_012E", + ea.GRADUATE_OR_PROFESSIONAL_DEGREE: "S1501_C01_013E", +} +S1501_18_TO_24_COLUMNS = { + "all": "S1501_C01_001E", + "less_than_high_school_graduate": "S1501_C01_002E", + ea.HIGH_SCHOOL_GRADUATE: "S1501_C01_003E", + "some_college_or_associates_degree": "S1501_C01_004E", + "bachelors_degree_or_higher": "S1501_C01_005E", +} +SHORT = { + ea.LESS_THAN_9TH_GRADE: "< 9th grade", + ea.GRADE_9_TO_12_NO_DIPLOMA: "9th-12th, no diploma", + ea.HIGH_SCHOOL_GRADUATE: "High school or GED", + ea.SOME_COLLEGE_NO_DEGREE: "Some college, no degree", + ea.ASSOCIATES_DEGREE: "Associate's", + ea.BACHELORS_DEGREE: "Bachelor's", + ea.GRADUATE_OR_PROFESSIONAL_DEGREE: "Graduate or professional", +} + + +def _sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as handle: + for block in iter(lambda: handle.read(1 << 20), b""): + digest.update(block) + return digest.hexdigest() + + +def _git(*args: str) -> str: + return subprocess.run( + ["git", *args], cwd=REPO, check=True, capture_output=True, text=True + ).stdout.strip() + + +def _load_tool(): + path = REPO / "tools" / "build_us_fiscal_refresh_release.py" + spec = importlib.util.spec_from_file_location( + "build_us_fiscal_refresh_release", path + ) + module = importlib.util.module_from_spec(spec) + assert spec.loader is not None + spec.loader.exec_module(module) + return module + + +def _read_host(path: Path) -> Frame: + """The release's entity tables, reduced to what the stage and receipt read.""" + + person_columns = [ + "person_id", + "person_household_id", + "person_tax_unit_id", + "person_spm_unit_id", + "person_family_id", + "person_marital_unit_id", + "source_year", + "PERIDNUM", + "source_household_id", + "P_SEQ", + "A_LINENO", + "A_AGE", + "age", + "person_support_channel", + ] + with pd.HDFStore(path, "r") as store: + person = store.select("person", columns=person_columns) + household = store.select( + "household", columns=["household_id", "household_weight", "state_fips"] + ) + groups = { + entity: store.select(entity, columns=[f"{entity}_id"]) + for entity in ("tax_unit", "spm_unit", "family", "marital_unit") + } + person = person.reset_index(drop=True) + household = household.reset_index(drop=True) + weights = household["household_weight"].to_numpy(dtype=np.float64) + return Frame( + { + "person": person, + "household": household.drop(columns="household_weight"), + **{ + entity: table.reset_index(drop=True) for entity, table in groups.items() + }, + }, + US_SCHEMA, + {"household": Weights(weights, WeightKind.CALIBRATED)}, + ) + + +def _raw_s1501(path: Path) -> pd.DataFrame: + payload = json.loads(path.read_text(encoding="utf-8")) + rows = payload["response"]["data"] if "response" in payload else payload + raw = pd.DataFrame(rows[1:], columns=rows[0]) + raw["state_fips"] = raw["GEO_ID"].str.removeprefix("0400000US") + return raw.set_index("state_fips") + + +def _facts(path: Path) -> list[dict]: + return [json.loads(line) for line in path.read_text(encoding="utf-8").splitlines()] + + +def _entropy_calibrate( + base: np.ndarray, matrix: np.ndarray, targets: np.ndarray +) -> tuple[np.ndarray, dict[str, float]]: + """Minimum-KL household weights hitting ``matrix @ w = targets`` exactly. + + Newton on the dual with a backtracking line search; ``matrix`` is + constraints x households. + """ + + scale = np.maximum(np.abs(targets), 1.0) + a = matrix / scale[:, None] + t = targets / scale + lam = np.zeros(len(t)) + + def dual(values: np.ndarray) -> float: + return float(np.sum(base * np.exp(np.clip(a.T @ values, -50, 50))) - t @ values) + + iterations = 0 + for iterations in range(1, 201): # noqa: B007 + w = base * np.exp(np.clip(a.T @ lam, -50, 50)) + gradient = a @ w - t + if np.max(np.abs(gradient)) < 1e-10: + break + hessian = (a * w) @ a.T + 1e-12 * np.eye(len(t)) + step = np.linalg.solve(hessian, gradient) + size, current = 1.0, dual(lam) + while dual(lam - size * step) > current - 1e-4 * size * gradient @ step: + size /= 2 + if size < 1e-12: + break + lam = lam - size * step + w = base * np.exp(np.clip(a.T @ lam, -50, 50)) + ratio = w / base + return w, { + "iterations": iterations, + "max_abs_relative_error": float(np.max(np.abs(matrix @ w - targets) / scale)), + "weight_ratio_p01": float(np.quantile(ratio, 0.01)), + "weight_ratio_p50": float(np.quantile(ratio, 0.50)), + "weight_ratio_p99": float(np.quantile(ratio, 0.99)), + "weight_ratio_min": float(ratio.min()), + "weight_ratio_max": float(ratio.max()), + "kish_ess_before": float(base.sum() ** 2 / np.sum(base**2)), + "kish_ess_after": float(w.sum() ** 2 / np.sum(w**2)), + } + + +def _pct(value: float, digits: int = 1) -> str: + return f"{100 * value:.{digits}f}%" + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + parser.add_argument("--h5", type=Path, required=True) + parser.add_argument("--asec-archive", action="append", default=[], required=True) + parser.add_argument("--s1501-facts", type=Path, required=True) + parser.add_argument("--s1501-raw", type=Path, required=True) + parser.add_argument("--s1501-facts-source", default="") + parser.add_argument("--sidecar-dir", type=Path, required=True) + parser.add_argument("--run", default="") + args = parser.parse_args() + tool = _load_tool() + + # 1. The build stage on the published release. + frame = _read_host(args.h5) + archives = tool._asec_attainment_source_paths(args.asec_archive) + sources = ea.load_asec_attainment_sources( + frame.table("person")["source_year"].astype(int).unique(), archives + ) + frame, record = ea.with_us_cps_educational_attainment(frame, sources=sources) + gate = ea.us_cps_educational_attainment_signal_gate(frame) + person = frame.table("person") + household = frame.table("household") + weights = np.asarray(frame.weights_for("household").values, dtype=np.float64) + household_position = pd.Series( + np.arange(len(household)), index=household["household_id"].to_numpy() + ) + person_household = household_position.reindex( + person["person_household_id"].to_numpy() + ).to_numpy() + person_weight = weights[person_household] + person_state = household["state_fips"].to_numpy()[person_household] + classes = person[ea.US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN].to_numpy(dtype=object) + age = person["age"].to_numpy(dtype=np.float64) + + args.sidecar_dir.mkdir(parents=True, exist_ok=True) + sidecar = args.sidecar_dir / "populace_us_2024_cps_educational_attainment.csv.gz" + person[["person_id", "A_HGA", ea.US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN]].to_csv( + sidecar, index=False, compression={"method": "gzip", "mtime": 0} + ) + + # 2. The compile path on the draft S1501 facts. + facts = _facts(args.s1501_facts) + references = fiscal_targets._dynamic_us_fiscal_target_references( + tuple(facts), target_period=TARGET_PERIOD + ) + registry = compile_ledger_target_references(facts, references, country="us") + specs = [ + spec + for spec in registry.specs + if spec.family == ea.US_EDUCATIONAL_ATTAINMENT_TARGET_FAMILY + ] + if len(specs) != len(registry.specs): + raise SystemExit("S1501 facts compiled into a family other than attainment.") + unsupported = tool._unsupported_ledger_filter_metadata(specs) + if unsupported: + raise SystemExit(f"The tool would refuse these targets: {unsupported}") + + # 3. Every compiled value against the raw Census response. + raw = _raw_s1501(args.s1501_raw) + raw_mismatches = [] + for spec in specs: + fips = spec.metadata["state_fips"] + category = spec.metadata["educational_attainment_category"] + published = float(raw.loc[fips, S1501_25_PLUS_COLUMNS[category]]) + if published != float(spec.value): + raw_mismatches.append((spec.name, published, float(spec.value))) + partition_gaps = { + fips: float(raw.loc[fips, S1501_25_PLUS_COLUMNS["all"]]) + - sum( + float(raw.loc[fips, column]) + for category, column in S1501_25_PLUS_COLUMNS.items() + if category != "all" + ) + for fips in US_STATE_FIPS_TO_POSTAL + } + + # 4. The tool's materializer, cell by cell. + cells = [] + for spec in specs: + values = tool._population_attainment_household_values( + frame=frame, household=household, age=age, metadata=spec.metadata + ) + indicator = ea.attainment_target_person_indicator(classes, age, spec.metadata) + state = int(spec.metadata["state_fips"]) + in_cell = (indicator > 0) & (person_state == state) + estimate = float(weights @ values) + direct = float(person_weight[in_cell].sum()) + if not np.isclose(estimate, direct, rtol=1e-12): + raise SystemExit(f"{spec.name}: materializer {estimate} != direct {direct}") + cells.append( + { + "name": spec.name, + "state_fips": spec.metadata["state_fips"], + "state": US_STATE_FIPS_TO_POSTAL[spec.metadata["state_fips"]], + "category": spec.metadata["educational_attainment_category"], + "target": float(spec.value), + "estimate": estimate, + "relative_error": estimate / float(spec.value) - 1.0, + "records": int(in_cell.sum()), + "households": int(np.unique(person_household[in_cell]).size), + } + ) + table = pd.DataFrame(cells) + total_target = table.groupby("state_fips")["target"].transform("sum") + total_estimate = table.groupby("state_fips")["estimate"].transform("sum") + table["target_share"] = table["target"] / total_target + table["estimate_share"] = table["estimate"] / total_estimate + table["share_error_pp"] = 100 * (table["estimate_share"] - table["target_share"]) + + # 5. The 18-to-24 universe, held out (not compiled). + held_out = [] + for fips in US_STATE_FIPS_TO_POSTAL: + mask = (person_state == int(fips)) & (age >= 18) & (age < 25) + total = float(person_weight[mask].sum()) + for category, column in S1501_18_TO_24_COLUMNS.items(): + if category == "all": + continue + members = ea.S1501_ATTAINMENT_CATEGORY_CLASSES[category] + in_cat = mask & np.isin(classes, sorted(members)) + held_out.append( + { + "state_fips": fips, + "category": category, + "target_share": float(raw.loc[fips, column]) + / float(raw.loc[fips, S1501_18_TO_24_COLUMNS["all"]]), + "estimate_share": float(person_weight[in_cat].sum()) / total, + } + ) + held = pd.DataFrame(held_out) + held["share_error_pp"] = 100 * (held["estimate_share"] - held["target_share"]) + + # 6. A standalone per-state entropy calibration to the cells, keeping each + # state's population under 25 fixed. Not the release solve: it shows what + # binding these cells alone asks of the weights. + calibration = {} + calibrated_weights = weights.copy() + category_order = list(ea.US_EDUCATIONAL_ATTAINMENT_CLASSES) + for fips in US_STATE_FIPS_TO_POSTAL: + state = int(fips) + households = np.flatnonzero(household["state_fips"].to_numpy() == state) + local = pd.Series(np.arange(len(households)), index=households) + in_state = person_state == state + rows = np.zeros((len(category_order) + 1, len(households))) + hh_index = local.reindex(person_household[in_state]).to_numpy() + state_classes = classes[in_state] + state_age = age[in_state] + for row, label in enumerate(category_order): + np.add.at( + rows[row], + hh_index, + ((state_classes == label) & (state_age >= 25)) * 1.0, + ) + np.add.at(rows[-1], hh_index, (state_age < 25) * 1.0) + state_cells = table.loc[table["state_fips"] == fips].set_index("category") + targets = np.array( + [*state_cells.loc[category_order, "target"], rows[-1] @ weights[households]] + ) + fitted, summary = _entropy_calibrate(weights[households], rows, targets) + calibrated_weights[households] = fitted + before = float(rows.sum(axis=0) @ weights[households]) + after = float(rows.sum(axis=0) @ fitted) + summary["state_population_change"] = after / before - 1.0 + calibration[fips] = summary + calibrated_estimate = [] + for spec, cell in zip(specs, cells, strict=True): + values = tool._population_attainment_household_values( + frame=frame, household=household, age=age, metadata=spec.metadata + ) + calibrated_estimate.append( + float(calibrated_weights @ values) / cell["target"] - 1 + ) + table["calibrated_relative_error"] = calibrated_estimate + + # 7. National and ROI-class summaries. + national = ( + table.groupby("category")[["target", "estimate"]].sum().reindex(category_order) + ) + national["target_share"] = national["target"] / national["target"].sum() + national["estimate_share"] = national["estimate"] / national["estimate"].sum() + roi = { + role: { + "class": label, + "share_error_pp_mean_abs": float( + table.loc[table["category"] == label, "share_error_pp"].abs().mean() + ), + "share_error_pp_max_abs": float( + table.loc[table["category"] == label, "share_error_pp"].abs().max() + ), + "relative_error_median_abs": float( + table.loc[table["category"] == label, "relative_error"].abs().median() + ), + "records_min": int(table.loc[table["category"] == label, "records"].min()), + } + for role, label in ea.US_DEGREE_ROI_CLASSES.items() + } + level_gap = ( + table.groupby("state_fips")[["target", "estimate"]] + .sum() + .pipe(lambda frame_: frame_["target"] / frame_["estimate"] - 1.0) + ) + payload = { + "schema_version": 1, + "issue": "PolicyEngine/microcosm#297", + "generated_at": datetime.now(UTC).isoformat(timespec="seconds"), + "commit": _git("rev-parse", "HEAD"), + "modal_run": args.run, + "host": { + "release": HOST_RELEASE, + "path": args.h5.name, + "sha256": _sha256(args.h5), + "persons": len(person), + "households": len(household), + }, + "s1501": { + "status": "TEMPORARY draft input: PolicyEngine/chronicle#347 is unmerged", + "source": args.s1501_facts_source, + "facts_sha256": _sha256(args.s1501_facts), + "facts": len(facts), + "raw_sha256": _sha256(args.s1501_raw), + "compiled_targets": len(specs), + "raw_value_mismatches": raw_mismatches, + "max_abs_partition_gap": max(abs(gap) for gap in partition_gaps.values()), + }, + "stage": { + "derivation": record, + "signal_gate_passed": gate.passed, + "signal_gate_failures": list(gate.failures), + "signal_gate": dict(gate.details), + }, + "sidecar": { + "file": sidecar.name, + "sha256": _sha256(sidecar), + "rows": len(person), + "columns": ["person_id", "A_HGA", ea.US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN], + }, + "national_25_plus": { + label: { + "target": float(national.loc[label, "target"]), + "estimate": float(national.loc[label, "estimate"]), + "target_share": float(national.loc[label, "target_share"]), + "estimate_share": float(national.loc[label, "estimate_share"]), + } + for label in category_order + }, + "state_25_plus_level_gap": { + "description": "S1501 25+ total / release 25+ weighted population - 1", + "by_state": { + US_STATE_FIPS_TO_POSTAL[k]: float(v) for k, v in level_gap.items() + }, + "max_abs": float(level_gap.abs().max()), + "median_abs": float(level_gap.abs().median()), + }, + "cells": { + "share_error_pp_mean_abs": float(table["share_error_pp"].abs().mean()), + "share_error_pp_p90_abs": float( + table["share_error_pp"].abs().quantile(0.9) + ), + "share_error_pp_max_abs": float(table["share_error_pp"].abs().max()), + "relative_error_median_abs": float(table["relative_error"].abs().median()), + "relative_error_p90_abs": float( + table["relative_error"].abs().quantile(0.9) + ), + "relative_error_max_abs": float(table["relative_error"].abs().max()), + "records_min": int(table["records"].min()), + "households_min": int(table["households"].min()), + "rows": table.to_dict(orient="records"), + }, + "roi_classes": roi, + "held_out_18_to_24": { + "reason": ( + "Not compiled: the ACS counts college students in dormitories " + "(group quarters) in the state of their college, the CPS in their " + "parents' household." + ), + "share_error_pp_mean_abs": float(held["share_error_pp"].abs().mean()), + "share_error_pp_max_abs": float(held["share_error_pp"].abs().max()), + "national_by_category": { + category: float( + held.loc[held["category"] == category, "share_error_pp"].mean() + ) + for category in held["category"].unique() + }, + }, + "standalone_calibration": { + "description": ( + "Per-state minimum-KL reweighting of the release's household " + "weights to the seven 25+ cells, holding the state's population " + "under 25 fixed. Not the release solve, which fits every target " + "jointly; it shows what binding these cells alone asks of the " + "weights." + ), + "max_abs_relative_error_after": float( + table["calibrated_relative_error"].abs().max() + ), + "weight_ratio_p01_min": min( + v["weight_ratio_p01"] for v in calibration.values() + ), + "weight_ratio_p99_max": max( + v["weight_ratio_p99"] for v in calibration.values() + ), + "weight_ratio_min": min( + v["weight_ratio_min"] for v in calibration.values() + ), + "weight_ratio_max": max( + v["weight_ratio_max"] for v in calibration.values() + ), + "kish_ess_ratio_min": min( + v["kish_ess_after"] / v["kish_ess_before"] for v in calibration.values() + ), + "by_state": {US_STATE_FIPS_TO_POSTAL[k]: v for k, v in calibration.items()}, + }, + } + RECEIPT_JSON.parent.mkdir(parents=True, exist_ok=True) + RECEIPT_JSON.write_text( + json.dumps(payload, indent=2, sort_keys=True, default=float) + "\n", + encoding="utf-8", + newline="\n", + ) + RECEIPT_MD.write_text( + _markdown(payload, table, national, held), encoding="utf-8", newline="\n" + ) + print(f"wrote {RECEIPT_JSON.relative_to(REPO)} and {RECEIPT_MD.relative_to(REPO)}") + + +def _markdown(payload, table, national, held) -> str: + cells = payload["cells"] + gap = payload["state_25_plus_level_gap"] + calibration = payload["standalone_calibration"] + lines = [ + "# microcosm#297 receipt: CPS educational attainment against ACS S1501", + "", + f"Generated {payload['generated_at'][:10]} by " + "`experiments/build_297_attainment_receipt.py` at commit " + f"`{payload['commit']}`, Modal run `{payload['modal_run']}` " + "(`experiments/modal_297.py`). Machine-readable copy: " + "`experiments/receipts/297-cps-educational-attainment-s1501.json`.", + "", + f"The build stage ran on the published release `{payload['host']['release']}` " + f"({payload['host']['persons']:,} persons, {payload['host']['households']:,} " + "households) at its calibrated weights. Every person joined its own Census " + "member row; the signal gate " + f"{'passed' if payload['stage']['signal_gate_passed'] else 'FAILED'}. " + "The S1501 facts are a **temporary draft input** " + "(PolicyEngine/chronicle#347, unmerged): " + f"{payload['s1501']['facts']} facts, {payload['s1501']['compiled_targets']} " + "compiled targets (51 states and DC x 7 classes, population 25 and over), " + f"{len(payload['s1501']['raw_value_mismatches'])} mismatches against the raw " + "Census response, largest gap between a state's categories and its total " + f"{payload['s1501']['max_abs_partition_gap']:.0f}.", + "", + "## Classes", + "", + "| Class | CPS ASEC `A_HGA` | ACS PUMS `SCHL` | Six-class view |", + "|---|---|---|---|", + "| `less_than_9th_grade` | 31-34 | 01-11 | less than high school |", + "| `9th_to_12th_grade_no_diploma` | 35-38 | 12-15 | less than high school |", + "| `high_school_graduate_includes_equivalency` | 39 | 16, 17 | high school or GED |", + "| `some_college_no_degree` | 40 | 18, 19 | some college, no degree |", + "| `associates_degree` | 41, 42 | 20 | associate's |", + "| `bachelors_degree` | 43 | 21 | bachelor's |", + "| `graduate_or_professional_degree` | 44, 45, 46 | 22, 23, 24 | graduate or professional |", + "| `not_in_universe` | 0 (Children) | blank, or under 15 | |", + "", + "## National, population 25 and over (sum of the 51 state cells)", + "", + "| Class | S1501 | Release | S1501 share | Release share |", + "|---|---:|---:|---:|---:|", + ] + for label, row in national.iterrows(): + lines.append( + f"| {SHORT[label]} | {row['target'] / 1e6:.2f}M | {row['estimate'] / 1e6:.2f}M " + f"| {_pct(row['target_share'])} | {_pct(row['estimate_share'])} |" + ) + lines += [ + "", + "## State cells (357)", + "", + "| Measure | Value |", + "|---|---:|", + f"| Mean abs share error | {cells['share_error_pp_mean_abs']:.2f} pp |", + f"| 90th percentile abs share error | {cells['share_error_pp_p90_abs']:.2f} pp |", + f"| Max abs share error | {cells['share_error_pp_max_abs']:.2f} pp |", + f"| Median abs level error | {_pct(cells['relative_error_median_abs'])} |", + f"| 90th percentile abs level error | {_pct(cells['relative_error_p90_abs'])} |", + f"| Max abs level error | {_pct(cells['relative_error_max_abs'])} |", + f"| Fewest records in a cell | {cells['records_min']} |", + f"| Fewest households in a cell | {cells['households_min']} |", + f"| S1501 25+ total vs release 25+ population, median abs | {_pct(gap['median_abs'], 2)} |", + f"| S1501 25+ total vs release 25+ population, max abs | {_pct(gap['max_abs'], 2)} |", + "", + "Share error is the release's share of a state's population 25 and over in a " + "class minus S1501's; level error compares counts.", + "", + "### Classes the degree-ROI analysis uses", + "", + "Two-year degree = `associates_degree`, four-year degree = " + "`bachelors_degree`, each against the " + "`high_school_graduate_includes_equivalency` baseline.", + "", + "| Role | Class | Mean abs share error | Max abs share error | Median abs level error | Fewest records |", + "|---|---|---:|---:|---:|---:|", + ] + for role, row in payload["roi_classes"].items(): + lines.append( + f"| {role} | `{row['class']}` | {row['share_error_pp_mean_abs']:.2f} pp " + f"| {row['share_error_pp_max_abs']:.2f} pp " + f"| {_pct(row['relative_error_median_abs'])} | {row['records_min']} |" + ) + worst = table.reindex( + table["share_error_pp"].abs().sort_values(ascending=False).index + ).head(10) + lines += [ + "", + "### Largest share errors", + "", + "| State | Class | S1501 share | Release share | Error | Records |", + "|---|---|---:|---:|---:|---:|", + ] + for _, row in worst.iterrows(): + lines.append( + f"| {row['state']} | {SHORT[row['category']]} | {_pct(row['target_share'])} " + f"| {_pct(row['estimate_share'])} | {row['share_error_pp']:+.2f} pp " + f"| {row['records']} |" + ) + merged_release = float( + national.loc[ + [ea.SOME_COLLEGE_NO_DEGREE, ea.ASSOCIATES_DEGREE], "estimate_share" + ].sum() + ) + merged_s1501 = float( + national.loc[ + [ea.SOME_COLLEGE_NO_DEGREE, ea.ASSOCIATES_DEGREE], "target_share" + ].sum() + ) + some = table[table["category"] == ea.SOME_COLLEGE_NO_DEGREE] + assoc = table[table["category"] == ea.ASSOCIATES_DEGREE] + thin = table[table["records"] < 30] + worst_state, worst_ratio = max( + ( + (state, values["weight_ratio_max"]) + for state, values in calibration["by_state"].items() + ), + key=lambda item: item[1], + ) + lines += [ + "", + "### Reading the comparison", + "", + "- **Some college against associate's is an instrument difference.** " + f"Nationally the release has {_pct(national.loc[ea.SOME_COLLEGE_NO_DEGREE, 'estimate_share'])} " + "some college, no degree against S1501's " + f"{_pct(national.loc[ea.SOME_COLLEGE_NO_DEGREE, 'target_share'])}, and " + f"{_pct(national.loc[ea.ASSOCIATES_DEGREE, 'estimate_share'])} associate's against " + f"{_pct(national.loc[ea.ASSOCIATES_DEGREE, 'target_share'])}. The release is below " + f"S1501 on some college in {int((some['share_error_pp'] < 0).sum())} of 51 states " + f"and above it on associate's in {int((assoc['share_error_pp'] > 0).sum())}. The " + "gap has one sign almost everywhere, so it reads as a difference between " + "the instruments rather than sampling: the CPS interviews by telephone or " + "visit and offers occupational and academic associate's answers, the ACS is " + 'mostly self-response and includes group quarters (Census, "Educational ' + 'Attainment Fact Sheet", ' + "https://www.census.gov/topics/education/educational-attainment/guidance/" + "factsheet-acs-cps.html). Binding the two cells separately would move " + "weight to settle a definition. Their sum is " + f"{100 * (merged_release - merged_s1501):+.1f} pp off nationally " + f"({_pct(merged_release)} against {_pct(merged_s1501)}), less than the " + "some-college cell alone; the merged rows below give the state spread.", + "- **Thin cells.** " + f"{len(thin)} cells have fewer than 30 records; " + f"{int((thin['category'] == ea.LESS_THAN_9TH_GRADE).sum())} of them are " + "`less_than_9th_grade`. The standalone calibration's largest weight ratio " + f"({worst_ratio:.0f}) is in {worst_state}. Merging the two classes below a " + "diploma (the six-class view) thickens those cells.", + ] + merged = ( + table.assign( + merged=table["category"].map( + { + ea.SOME_COLLEGE_NO_DEGREE: "some_college_or_associates", + ea.ASSOCIATES_DEGREE: "some_college_or_associates", + ea.LESS_THAN_9TH_GRADE: "less_than_high_school", + ea.GRADE_9_TO_12_NO_DIPLOMA: "less_than_high_school", + } + ) + ) + .dropna(subset=["merged"]) + .groupby(["merged", "state_fips"])[["target_share", "estimate_share"]] + .sum() + ) + merged["error"] = 100 * (merged["estimate_share"] - merged["target_share"]) + lines += [ + "", + "| Merged row | Mean abs share error | Max abs share error |", + "|---|---:|---:|", + ] + for name, group in merged.groupby(level=0): + lines.append( + f"| {name} | {group['error'].abs().mean():.2f} pp " + f"| {group['error'].abs().max():.2f} pp |" + ) + held_national = payload["held_out_18_to_24"]["national_by_category"] + lines += [ + "", + "## Held out: population 18 to 24", + "", + payload["held_out_18_to_24"]["reason"], + f"Mean abs share error {payload['held_out_18_to_24']['share_error_pp_mean_abs']:.2f} pp, " + f"max {payload['held_out_18_to_24']['share_error_pp_max_abs']:.2f} pp; mean " + "signed error by category: " + + ", ".join(f"{k} {v:+.2f} pp" for k, v in held_national.items()) + + ".", + "", + "## Standalone calibration to the cells", + "", + calibration["description"], + "", + "| Measure | Value |", + "|---|---:|", + f"| Max abs level error after | {_pct(calibration['max_abs_relative_error_after'], 4)} |", + f"| Weight ratio, lowest state 1st percentile | {calibration['weight_ratio_p01_min']:.3f} |", + f"| Weight ratio, highest state 99th percentile | {calibration['weight_ratio_p99_max']:.3f} |", + f"| Weight ratio, min / max | {calibration['weight_ratio_min']:.3f} / {calibration['weight_ratio_max']:.3f} |", + f"| Kish effective sample size kept, lowest state | {_pct(calibration['kish_ess_ratio_min'])} |", + "", + "## SCF education-debt imputation (microcosm#1073, PR #1246)", + "", + "The #1073 hold-out already measured SCF `educ` as a predictor: " + "`build_plus_education` raised the household rank correlation (0.168 to 0.207) " + "but moved the share with debt from -0.30 pp to -0.92 pp. With this column " + "the host side of that predictor exists: map SCF `educ` (reference person) " + "and the host reference person's `cps_educational_attainment` to the same " + "seven classes, and condition the QRFs on it. The share error suggests " + "adding it with the share calibrated to FSA borrower counts " + "(microcosm#1074) rather than as a bare predictor. Nothing here changes #1246.", + "", + ] + return "\n".join(lines) + + +if __name__ == "__main__": + main() diff --git a/experiments/modal_297.py b/experiments/modal_297.py new file mode 100644 index 0000000000..3282885bba --- /dev/null +++ b/experiments/modal_297.py @@ -0,0 +1,566 @@ +"""Run the microcosm#297 educational-attainment work on Modal instead of local RAM. + +Each run clones a pushed commit of PolicyEngine/microcosm, syncs that tree's +uv.lock, fetches the inputs and verifies each sha256, runs the requested steps +in order, and saves every receipt the steps write plus a run log to the +`microcosm-297-cache` volume under results//. `collect` copies a +run's files back into this checkout. Inputs: + +- the published host release `populace-us-2024-spm-20260915` from Hugging Face + (policyengine/populace-us at a pinned revision); +- the official Census CPS ASEC public-use person archives for the host's + pooled income years (asecpub23/24/25csv.zip, the pins in + ``microcosm.build.us_runtime.education_assistance_source``); +- the ACS 2024 1-year S1501 state attainment facts, built with + ``chronicle build-bundle`` from the DRAFT Chronicle package + ``packages/census/acs_s1501_state_2024``. TEMPORARY: PolicyEngine/chronicle#347 + is unmerged, so the package is read from the author's fork at a pinned + commit (CHRONICLE_DRAFT below) and the facts are checked against the digest + of a local build. Nothing in the repository pins the fork; replace this input + with the pinned US feed once #347 merges and the feed is re-pinned. + + export PYTHONIOENCODING=utf-8 PYTHONUTF8=1 + modal run experiments/modal_297.py::preflight --commit + modal run --detach experiments/modal_297.py::launch --commit --steps tests,receipt + modal run experiments/modal_297.py::collect --run-id + +Steps (see STEPS; each runs one or more commands, stopping at the first that +fails): + +- ``tests``: the engine-free tests the attainment work touches; +- ``contract``: the engine-contract tests that read the stored-input register + and the US spec bundle; +- ``receipt``: the build stage on the host release (the exact Census join that + writes ``A_HGA`` and ``cps_educational_attainment``), the S1501 target + compile, and the state-totals receipt, labelled with the run id. + +After the steps the run saves every tracked file they changed +(``git status --porcelain``) and every untracked file matching OUTPUT_GLOBS, +so ``collect`` brings receipts back. This is an experiment runner, not the +registered stage runner in tools/modal_us_stage.py; it writes nothing to the +Hub and publishes nothing. +""" + +from __future__ import annotations + +import hashlib +import json +import os +import subprocess +import time +import urllib.request +from datetime import UTC, datetime +from pathlib import Path + +import modal + +REPO_URL = "https://github.com/PolicyEngine/microcosm.git" +HOST = { + "repo_id": "policyengine/populace-us", + "filename": "populace_us_2024.h5", + "revision": "8ab57ffc2ca41d8af631ff62ebbce95e966299f3", + "sha256": "6496cc4393d4d3c6574f76eca231de5898c803b9067645591fd5c4d3e65aee84", +} +#: income year -> (official archive url, archive sha256). The same pins as +#: microcosm.build.us_runtime.education_assistance_source.ASEC_EDUCATION_ASSISTANCE_ARCHIVES; +#: the build stage re-verifies the archive and its person member against them. +ASEC_ARCHIVES = { + 2022: ( + "https://www2.census.gov/programs-surveys/cps/datasets/2023/march/asecpub23csv.zip", + "d2e000250782adfbdd7f29c82b66d866591a30f0d330496698ec19f9c784ce11", + ), + 2023: ( + "https://www2.census.gov/programs-surveys/cps/datasets/2024/march/asecpub24csv.zip", + "cdb39cdac34bef99dd0940ab28e306f692404c2eea44d85dfd634214872a0a09", + ), + 2024: ( + "https://www2.census.gov/programs-surveys/cps/datasets/2025/march/asecpub25csv.zip", + "318845a2b5e0034eb2973898de1738f4df0025727de38499e7669cb9c0deef0b", + ), +} +#: TEMPORARY (PolicyEngine/chronicle#347, unmerged): the draft S1501 package on +#: the author's fork, at the head that also carries the raw files on R2. The facts are rebuilt here with that commit's own lock +#: (`chronicle build-bundle --year 2024 --source `), cached under +#: their digest, and the receipt checks every value against the raw Census +#: response the package pins. +CHRONICLE_DRAFT = { + "repo_url": "https://github.com/DTrim99/chronicle.git", + "commit": "81e3f986ccc47571a427a4adda8d4b49560d03bf", + "package": "packages/census/acs_s1501_state_2024", + "raw": "db/data/census/acs_s1501_state_2024/acs_S1501_state_2024.json", + "raw_sha256": "84fff08c9d2793a90f2326eb68ae8ba4d5e18957899fc8cdda015d26520f73a4", + "year": 2024, + "label": "TEMPORARY draft input: PolicyEngine/chronicle#347 (fork DTrim99/chronicle)", +} +_TESTS = "packages/microcosm-build/tests" +#: step -> commands. A part "glob:" expands to the sorted matches. +STEPS: dict[str, list[list[str]]] = { + "tests": [ + [ + "{python}", + "-m", + "pytest", + "-q", + f"{_TESTS}/engine_free/us/test_us_educational_attainment.py", + f"{_TESTS}/engine_free/us/test_us_fiscal_targets.py", + f"{_TESTS}/engine_free/us/test_us_stored_input_register.py", + f"{_TESTS}/engine_free/us/test_us_chronicle_feed.py", + "packages/microcosm-calibrate/tests/engine_free/shared/test_variable_labels.py", + "packages/microcosm-data/tests/engine_free/us/test_stored_inputs.py", + ], + [ + "{python}", + "-m", + "pytest", + "-q", + f"{_TESTS}/engine_free/us/test_us_fiscal_refresh_builder.py", + "-k", + "attainment or population_age or ledger_filter or restated", + ], + ["{python}", "tools/ci_test_plan.py", "verify"], + ], + "contract": [ + [ + "{python}", + "-m", + "pytest", + "-q", + f"{_TESTS}/engine_contract/us/test_us_stored_input_register.py", + f"{_TESTS}/engine_contract/us/test_us_spec_bundle.py", + f"{_TESTS}/engine_contract/us/test_us_bundle_core_contracts.py", + "packages/microcosm-data/tests/engine_contract/us/test_stored_inputs.py", + ], + ], + "receipt": [ + [ + "{python}", + "experiments/build_297_attainment_receipt.py", + "--h5", + "{h5}", + "--asec-archive", + "2022={asec_2022}", + "--asec-archive", + "2023={asec_2023}", + "--asec-archive", + "2024={asec_2024}", + "--s1501-facts", + "{s1501_facts}", + "--s1501-raw", + "{s1501_raw}", + "--s1501-facts-source", + "{s1501_source}", + "--sidecar-dir", + "{results}", + "--run", + "{run_id}", + ] + ], +} +OUTPUT_GLOBS = ("experiments/receipts/297-*.json", "experiments/297-*.md") +CPU = 8.0 +MEMORY_MB = 32768 + +image = ( + modal.Image.debian_slim(python_version="3.14") + .apt_install("git") + .pip_install("uv==0.11.7", "huggingface_hub") +) +app = modal.App("microcosm-297-experiments") +cache = modal.Volume.from_name("microcosm-297-cache", create_if_missing=True) +CACHE = Path("/cache") +WORK = Path("/work/microcosm") +CHRONICLE = Path("/work/chronicle") +VENV = Path("/opt/venv") +CHRONICLE_VENV = Path("/opt/chronicle-venv") + + +def _sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as handle: + for block in iter(lambda: handle.read(1 << 20), b""): + digest.update(block) + return digest.hexdigest() + + +def _verified(path: Path, sha256: str) -> bool: + return path.exists() and _sha256(path) == sha256 + + +def _clean_env(**overrides: str) -> dict[str, str]: + """The container environment without the Modal runtime's Python path. + + Modal puts its own client and dependencies (under /pkg) on PYTHONPATH. A + subprocess that inherits it sees those packages beside the venv's, and the + build's worker-identity check refuses the duplicates (e.g. idna). + """ + env = { + key: value + for key, value in os.environ.items() + if key not in {"PYTHONPATH", "PYTHONHOME", "PYTHONSTARTUP"} + } + env.update(overrides) + return env + + +def _uv_env(venv: Path) -> dict[str, str]: + return _clean_env( + **{ + "UV_PROJECT_ENVIRONMENT": str(venv), + # A Modal volume cannot host uv's cache: uv persists temporary files + # by atomic rename, which the volume refuses. + "UV_CACHE_DIR": "/root/.cache/uv", + "UV_LINK_MODE": "copy", + } + ) + + +def _clone(url: str, commit: str, target: Path) -> None: + target.mkdir(parents=True, exist_ok=True) + run = lambda *args: subprocess.run(args, cwd=target, check=True) # noqa: E731 + run("git", "init", "-q") + run("git", "remote", "add", "origin", url) + run("git", "fetch", "-q", "--depth", "1", "origin", commit) + run("git", "checkout", "-q", "--detach", "FETCH_HEAD") + head = subprocess.run( + ["git", "rev-parse", "HEAD"], + cwd=target, + check=True, + capture_output=True, + text=True, + ).stdout.strip() + if head != commit: + raise RuntimeError(f"checked out {head}, expected {commit}") + + +def _checkout(commit: str) -> None: + _clone(REPO_URL, commit, WORK) + subprocess.run( + ["uv", "sync", "--all-packages", "--extra", "us", "--frozen"], + cwd=WORK, + env=_uv_env(VENV), + check=True, + ) + + +def _download(url: str, sha256: str, target: Path) -> None: + if _verified(target, sha256): + return + target.parent.mkdir(parents=True, exist_ok=True) + request = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) + with urllib.request.urlopen(request, timeout=900) as response: + target.write_bytes(response.read()) + if not _verified(target, sha256): + raise RuntimeError(f"{target.name} sha256 mismatch") + + +def _s1501_facts() -> tuple[Path, Path]: + """Build the draft S1501 consumer facts once per commit; return facts and raw.""" + + root = CACHE / "s1501" / CHRONICLE_DRAFT["commit"] + facts = root / "consumer_facts.jsonl" + raw = root / "acs_S1501_state_2024.json" + if facts.exists() and _verified(raw, CHRONICLE_DRAFT["raw_sha256"]): + return facts, raw + _clone(CHRONICLE_DRAFT["repo_url"], CHRONICLE_DRAFT["commit"], CHRONICLE) + env = _uv_env(CHRONICLE_VENV) + subprocess.run(["uv", "sync", "--frozen"], cwd=CHRONICLE, env=env, check=True) + out = Path("/tmp/s1501-bundle") + subprocess.run( + [ + str(CHRONICLE_VENV / "bin" / "chronicle"), + "build-bundle", + "--year", + str(CHRONICLE_DRAFT["year"]), + "--source", + CHRONICLE_DRAFT["package"], + "--out", + str(out), + "--replace", + ], + cwd=CHRONICLE, + env=env, + check=True, + stdout=subprocess.DEVNULL, + ) + source_raw = CHRONICLE / CHRONICLE_DRAFT["raw"] + if not _verified(source_raw, CHRONICLE_DRAFT["raw_sha256"]): + raise RuntimeError("draft S1501 raw Census response sha256 mismatch") + root.mkdir(parents=True, exist_ok=True) + raw.write_bytes(source_raw.read_bytes()) + facts.write_bytes((out / "consumer_facts.jsonl").read_bytes()) + return facts, raw + + +def _inputs() -> dict[str, Path]: + from huggingface_hub import hf_hub_download + + host_dir = CACHE / "host" / HOST["revision"] + host = host_dir / HOST["filename"] + if not _verified(host, HOST["sha256"]): + hf_hub_download( + repo_id=HOST["repo_id"], + filename=HOST["filename"], + revision=HOST["revision"], + repo_type="dataset", + local_dir=host_dir, + ) + if not _verified(host, HOST["sha256"]): + raise RuntimeError("host H5 sha256 mismatch") + paths: dict[str, Path] = {"h5": host} + for year, (url, sha256) in ASEC_ARCHIVES.items(): + archive = CACHE / "asec" / url.rsplit("/", 1)[-1] + _download(url, sha256, archive) + paths[f"asec_{year}"] = archive + paths["s1501_facts"], paths["s1501_raw"] = _s1501_facts() + cache.commit() + return paths + + +def _expand(command: list[str], fields: dict[str, str]) -> list[str]: + parts: list[str] = [] + for part in command: + if part.startswith("glob:"): + matches = sorted(WORK.glob(part.removeprefix("glob:"))) + if not matches: + raise RuntimeError(f"{part} matched nothing") + parts.extend(str(path.relative_to(WORK)) for path in matches) + else: + parts.append(part.format(**fields)) + return parts + + +def _save_changed_files(target_root: Path) -> list[str]: + """Copy tracked files the steps changed, and new outputs, under target_root.""" + + status = subprocess.run( + ["git", "status", "--porcelain", "--untracked-files=all"], + cwd=WORK, + check=True, + capture_output=True, + text=True, + ).stdout.splitlines() + saved = [] + for line in status: + code, rel = line[:2], line[3:] + path = WORK / rel + untracked = code == "??" + if untracked and not any(path.match(p) for p in OUTPUT_GLOBS): + continue + if not path.is_file(): + continue + target = target_root / rel + target.parent.mkdir(parents=True, exist_ok=True) + target.write_bytes(path.read_bytes()) + saved.append(f"{code} {rel}") + return saved + + +@app.function( + image=image, cpu=2.0, memory=8192, timeout=3600, volumes={"/cache": cache} +) +def preflight_remote(commit: str) -> dict: + """Clone, sync and stage the inputs without running a step.""" + started = time.time() + _checkout(commit) + paths = _inputs() + probe = subprocess.run( + [ + str(VENV / "bin" / "python"), + "-c", + "import microcosm.build.us_runtime.educational_attainment as m; " + "print(m.__file__)", + ], + cwd=WORK, + capture_output=True, + text=True, + env=_clean_env(), + ) + return { + "commit": commit, + "inputs": {key: str(path) for key, path in paths.items()}, + "import_ok": probe.returncode == 0, + "import_output": (probe.stdout + probe.stderr)[-2000:], + "seconds": round(time.time() - started, 1), + } + + +@app.function( + image=image, cpu=CPU, memory=MEMORY_MB, timeout=4 * 3600, volumes={"/cache": cache} +) +def run_steps( + commit: str, steps: list[str], run_id: str, script_text: str = "" +) -> dict: + import resource # Unix-only; the local entrypoint runs on Windows too + + started = datetime.now(UTC) + _checkout(commit) + paths = _inputs() + out = CACHE / "results" / run_id + out.mkdir(parents=True, exist_ok=True) + fields = {key: str(path) for key, path in paths.items()} | { + "python": str(VENV / "bin" / "python"), + "run_id": run_id, + "results": str(out), + "s1501_source": ( + f"{CHRONICLE_DRAFT['repo_url']}@{CHRONICLE_DRAFT['commit']}:" + f"{CHRONICLE_DRAFT['package']} ({CHRONICLE_DRAFT['label']})" + ), + } + threads = str(int(CPU)) + env = _clean_env( + PYTHONUNBUFFERED="1", + OMP_NUM_THREADS=threads, + MKL_NUM_THREADS=threads, + OPENBLAS_NUM_THREADS=threads, + ) + (out / "s1501_consumer_facts.jsonl").write_bytes(paths["s1501_facts"].read_bytes()) + log = { + "run_id": run_id, + "commit": commit, + "steps": [], + "cpu": CPU, + "memory_mb": MEMORY_MB, + "inputs": { + "host": HOST, + "asec_archives": {str(k): v[1] for k, v in ASEC_ARCHIVES.items()}, + "s1501_draft": CHRONICLE_DRAFT, + "s1501_facts_sha256": _sha256(paths["s1501_facts"]), + }, + "started_at": started.isoformat(), + } + failed = False + for step in steps: + if step == "script": + # An uncommitted local probe passed by --script; it runs in the + # clone like any step, and the run log records its text. + (WORK / "_modal_probe.py").write_text(script_text, encoding="utf-8") + log["script_sha256"] = hashlib.sha256(script_text.encode()).hexdigest() + commands = [ + [ + fields["python"], + "_modal_probe.py", + json.dumps({key: value for key, value in fields.items()}), + ] + ] + else: + commands = [_expand(command, fields) for command in STEPS[step]] + before = resource.getrusage(resource.RUSAGE_CHILDREN).ru_maxrss + t0 = time.time() + returncodes = [] + with (out / f"{step}.log").open("w", encoding="utf-8") as handle: + for command in commands: + handle.write("$ " + " ".join(command) + "\n") + handle.flush() + result = subprocess.run( + command, + cwd=WORK, + env=env, + stdout=handle, + stderr=subprocess.STDOUT, + text=True, + ) + returncodes.append(result.returncode) + if result.returncode != 0: + break + peak_kb = resource.getrusage(resource.RUSAGE_CHILDREN).ru_maxrss + log["steps"].append( + { + "step": step, + "commands": commands, + "returncodes": returncodes, + "returncode": next((code for code in returncodes if code), 0), + "seconds": round(time.time() - t0, 1), + "peak_child_rss_gb": round(max(peak_kb, before) / 1024 / 1024, 2), + } + ) + cache.commit() + if any(returncodes): + failed = True + break + log["failed"] = failed + log["changed_files"] = _save_changed_files(out / "files") + log["finished_at"] = datetime.now(UTC).isoformat() + (out / "run.json").write_text(json.dumps(log, indent=2) + "\n", encoding="utf-8") + cache.commit() + return log + + +@app.function(image=image, volumes={"/cache": cache}) +def fetch_results(run_id: str) -> dict[str, bytes]: + root = CACHE / "results" / run_id + return { + str(p.relative_to(root)): p.read_bytes() + for p in root.rglob("*") + if p.is_file() and p.suffix != ".parquet" + } + + +def _check_commit(commit: str) -> None: + if len(commit) != 40 or any(c not in "0123456789abcdef" for c in commit): + raise SystemExit("--commit must be a full 40-hex sha that is pushed to GitHub") + + +def _names(steps: str, script: str) -> tuple[list[str], str]: + names = [s for s in steps.split(",") if s] + script_text = Path(script).read_text(encoding="utf-8") if script else "" + if script and "script" not in names: + names.append("script") + unknown = sorted(set(names) - set(STEPS) - {"script"}) + if unknown: + raise SystemExit(f"unknown steps: {unknown}") + return names, script_text + + +@app.local_entrypoint() +def preflight(commit: str) -> None: + _check_commit(commit) + print(json.dumps(preflight_remote.remote(commit), indent=2)) + + +@app.local_entrypoint() +def main(commit: str, steps: str = "tests,receipt", script: str = "") -> None: + _check_commit(commit) + names, script_text = _names(steps, script) + run_id = datetime.now(UTC).strftime("%Y%m%dT%H%M%SZ") + "-" + commit[:9] + print(f"run_id={run_id}") + print(json.dumps(run_steps.remote(commit, names, run_id, script_text), indent=2)) + + +@app.local_entrypoint() +def launch(commit: str, steps: str = "tests,receipt", script: str = "") -> None: + """Spawn the run and exit at once (use with ``modal run --detach``). + + ``main`` keeps a local client attached for the whole run, and stopping that + client (for example when the machine runs low on memory) cancels the + remote input even under --detach. ``launch`` returns as soon as the call is + spawned, so nothing local can cancel it; ``collect`` fetches the results. + """ + _check_commit(commit) + names, script_text = _names(steps, script) + run_id = datetime.now(UTC).strftime("%Y%m%dT%H%M%SZ") + "-" + commit[:9] + call = run_steps.spawn(commit, names, run_id, script_text) + print(f"run_id={run_id}") + print(f"function_call_id={call.object_id}") + + +@app.local_entrypoint() +def collect(run_id: str, logs_dir: str = "") -> None: + """Write a run's changed files into this checkout and its logs to logs_dir.""" + repo = Path(__file__).resolve().parents[1] + logs = ( + Path(logs_dir) + if logs_dir + else Path.home() / ".cache" / "microcosm" / "modal-297" / run_id + ) + logs.mkdir(parents=True, exist_ok=True) + for rel, data in fetch_results.remote(run_id).items(): + if rel.startswith("files/"): + target = repo / rel.removeprefix("files/") + target.parent.mkdir(parents=True, exist_ok=True) + target.write_bytes(data) + print("file", target.relative_to(repo)) + else: + path = logs / rel + path.parent.mkdir(parents=True, exist_ok=True) + path.write_bytes(data) + print("log", path) diff --git a/experiments/receipts/297-cps-educational-attainment-s1501.json b/experiments/receipts/297-cps-educational-attainment-s1501.json new file mode 100644 index 0000000000..6f165e7135 --- /dev/null +++ b/experiments/receipts/297-cps-educational-attainment-s1501.json @@ -0,0 +1,6323 @@ +{ + "cells": { + "households_min": 3, + "records_min": 4, + "relative_error_max_abs": 0.8328773334353852, + "relative_error_median_abs": 0.15336755191729456, + "relative_error_p90_abs": 0.46280362801868474, + "rows": [ + { + "calibrated_relative_error": 1.170175067954915e-13, + "category": "less_than_9th_grade", + "estimate": 104049.17303228614, + "estimate_share": 0.029440999885836882, + "households": 39, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.01.less_than_9th_grade.population", + "records": 45, + "relative_error": -0.16659319306447729, + "share_error_pp": -0.5826189012885483, + "state": "AL", + "state_fips": "01", + "target": 124848.0, + "target_share": 0.035267188898722365 + }, + { + "calibrated_relative_error": 5.023315097218983e-12, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 314755.37935679196, + "estimate_share": 0.08906090089571807, + "households": 104, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.01.9th_to_12th_grade_no_diploma.population", + "records": 136, + "relative_error": 0.2842597908366904, + "share_error_pp": 1.9828478064586055, + "state": "AL", + "state_fips": "01", + "target": 245087.0, + "target_share": 0.06923242283113201 + }, + { + "calibrated_relative_error": 3.042011087472929e-14, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1138272.819563613, + "estimate_share": 0.3220774271836348, + "households": 409, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.01.high_school_graduate_includes_equivalency.population", + "records": 569, + "relative_error": 0.07519134344376721, + "share_error_pp": 2.3023258343041366, + "state": "AL", + "state_fips": "01", + "target": 1058670.0, + "target_share": 0.29905416884059344 + }, + { + "calibrated_relative_error": 6.972200594645983e-14, + "category": "some_college_no_degree", + "estimate": 611547.7736472903, + "estimate_share": 0.17303912572709162, + "households": 270, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.01.some_college_no_degree.population", + "records": 309, + "relative_error": -0.14006159905492865, + "share_error_pp": -2.7848090623135118, + "state": "AL", + "state_fips": "01", + "target": 711153.0, + "target_share": 0.20088721635022674 + }, + { + "calibrated_relative_error": 5.218048215738236e-14, + "category": "associates_degree", + "estimate": 303371.652734026, + "estimate_share": 0.08583984411617734, + "households": 181, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.01.associates_degree.population", + "records": 198, + "relative_error": -0.11673968831441062, + "share_error_pp": -1.1183342772410163, + "state": "AL", + "state_fips": "01", + "target": 343468.0, + "target_share": 0.0970231868885875 + }, + { + "calibrated_relative_error": 4.618527782440651e-14, + "category": "bachelors_degree", + "estimate": 711108.2520228163, + "estimate_share": 0.20121003710548574, + "households": 319, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.01.bachelors_degree.population", + "records": 413, + "relative_error": 0.11538869068096802, + "share_error_pp": 2.111624776117782, + "state": "AL", + "state_fips": "01", + "target": 637543.0, + "target_share": 0.18009378934430792 + }, + { + "calibrated_relative_error": 2.55351295663786e-14, + "category": "graduate_or_professional_degree", + "estimate": 351053.8924697363, + "estimate_share": 0.09933166508605563, + "households": 215, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.01.graduate_or_professional_degree.population", + "records": 267, + "relative_error": -0.16274602790004034, + "share_error_pp": -1.9110361760374408, + "state": "AL", + "state_fips": "01", + "target": 419292.0, + "target_share": 0.11844202684643004 + }, + { + "calibrated_relative_error": 1.8197443552026016e-11, + "category": "less_than_9th_grade", + "estimate": 2576.11616250166, + "estimate_share": 0.005178806882227723, + "households": 10, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.02.less_than_9th_grade.population", + "records": 12, + "relative_error": -0.697816285923559, + "share_error_pp": -1.194227986996739, + "state": "AK", + "state_fips": "02", + "target": 8525.0, + "target_share": 0.017121086752195112 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 14012.146256831797, + "estimate_share": 0.028168838240272946, + "households": 45, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.02.9th_to_12th_grade_no_diploma.population", + "records": 49, + "relative_error": -0.42353452680989856, + "share_error_pp": -2.064784864366918, + "state": "AK", + "state_fips": "02", + "target": 24307.0, + "target_share": 0.048816686883942126 + }, + { + "calibrated_relative_error": 1.0906830993917538e-12, + "category": "high_school_graduate_includes_equivalency", + "estimate": 183057.23228963412, + "estimate_share": 0.36800283629387986, + "households": 332, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.02.high_school_graduate_includes_equivalency.population", + "records": 464, + "relative_error": 0.29105383555589026, + "share_error_pp": 8.324251142502437, + "state": "AK", + "state_fips": "02", + "target": 141789.0, + "target_share": 0.2847603248688555 + }, + { + "calibrated_relative_error": 1.3322676295501878e-15, + "category": "some_college_no_degree", + "estimate": 92474.67134886677, + "estimate_share": 0.1859032878192074, + "households": 235, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.02.some_college_no_degree.population", + "records": 282, + "relative_error": -0.17964363407525596, + "share_error_pp": -4.048668334104999, + "state": "AK", + "state_fips": "02", + "target": 112725.0, + "target_share": 0.22638997116025739 + }, + { + "calibrated_relative_error": 8.881784197001252e-16, + "category": "associates_degree", + "estimate": 51781.79756865314, + "estimate_share": 0.10409776295267932, + "households": 137, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.02.associates_degree.population", + "records": 158, + "relative_error": 0.0904874711730681, + "share_error_pp": 0.873180348898607, + "state": "AK", + "state_fips": "02", + "target": 47485.0, + "target_share": 0.09536595946369325 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 91097.45967717891, + "estimate_share": 0.18313465751152155, + "households": 258, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.02.bachelors_degree.population", + "records": 320, + "relative_error": -0.06792318411661102, + "share_error_pp": -1.31523260442018, + "state": "AK", + "state_fips": "02", + "target": 97736.0, + "target_share": 0.19628698355572335 + }, + { + "calibrated_relative_error": 4.440892098500626e-16, + "category": "graduate_or_professional_degree", + "estimate": 62434.874032694905, + "estimate_share": 0.1255138103002112, + "households": 188, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.02.graduate_or_professional_degree.population", + "records": 250, + "relative_error": -0.04471022181717488, + "share_error_pp": -0.574517701512206, + "state": "AK", + "state_fips": "02", + "target": 65357.0, + "target_share": 0.13125898731533325 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "less_than_9th_grade", + "estimate": 181337.72961620658, + "estimate_share": 0.03445710908347266, + "households": 88, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.04.less_than_9th_grade.population", + "records": 127, + "relative_error": -0.195070534897256, + "share_error_pp": -0.8293281684367881, + "state": "AZ", + "state_fips": "04", + "target": 225284.0, + "target_share": 0.04275039076784054 + }, + { + "calibrated_relative_error": 0.0, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 407652.37689590134, + "estimate_share": 0.07746056183987654, + "households": 136, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.04.9th_to_12th_grade_no_diploma.population", + "records": 151, + "relative_error": 0.2914532269380441, + "share_error_pp": 1.7561359733060526, + "state": "AZ", + "state_fips": "04", + "target": 315654.0, + "target_share": 0.05989920210681601 + }, + { + "calibrated_relative_error": 0.0, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1311520.6357472246, + "estimate_share": 0.24921018756997101, + "households": 416, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.04.high_school_graduate_includes_equivalency.population", + "records": 567, + "relative_error": 0.06724353255487037, + "share_error_pp": 1.6014058643245233, + "state": "AZ", + "state_fips": "04", + "target": 1228886.0, + "target_share": 0.23319612892672578 + }, + { + "calibrated_relative_error": 4.440892098500626e-16, + "category": "some_college_no_degree", + "estimate": 799124.5652475803, + "estimate_share": 0.15184662548878425, + "households": 284, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.04.some_college_no_degree.population", + "records": 337, + "relative_error": -0.32612972447506583, + "share_error_pp": -7.318726129869896, + "state": "AZ", + "state_fips": "04", + "target": 1185873.0, + "target_share": 0.2250338867874832 + }, + { + "calibrated_relative_error": 0.0, + "category": "associates_degree", + "estimate": 633629.2282346969, + "estimate_share": 0.12039982789002712, + "households": 228, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.04.associates_degree.population", + "records": 251, + "relative_error": 0.3101149362644773, + "share_error_pp": 2.862247134219652, + "state": "AZ", + "state_fips": "04", + "target": 483644.0, + "target_share": 0.0917773565478306 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 1229372.246758072, + "estimate_share": 0.2336006615964099, + "households": 346, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.04.bachelors_degree.population", + "records": 451, + "relative_error": 0.11570226826291008, + "share_error_pp": 2.450509298057535, + "state": "AZ", + "state_fips": "04", + "target": 1101882.0, + "target_share": 0.20909556861583456 + }, + { + "calibrated_relative_error": -3.3306690738754696e-16, + "category": "graduate_or_professional_degree", + "estimate": 700071.9716478093, + "estimate_share": 0.1330250265314586, + "households": 268, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.04.graduate_or_professional_degree.population", + "records": 345, + "relative_error": -0.03906226010211078, + "share_error_pp": -0.5222439716010691, + "state": "AZ", + "state_fips": "04", + "target": 728530.0, + "target_share": 0.13824746624746928 + }, + { + "calibrated_relative_error": 9.18309872588452e-12, + "category": "less_than_9th_grade", + "estimate": 38788.9243013488, + "estimate_share": 0.018485852145969563, + "households": 50, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.05.less_than_9th_grade.population", + "records": 63, + "relative_error": -0.5459300637828645, + "share_error_pp": -2.2218498704807357, + "state": "AR", + "state_fips": "05", + "target": 85425.0, + "target_share": 0.04070435085077692 + }, + { + "calibrated_relative_error": 1.7923440509548527e-12, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 102746.42879490707, + "estimate_share": 0.04896643372920233, + "households": 79, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.05.9th_to_12th_grade_no_diploma.population", + "records": 96, + "relative_error": -0.26218652576579393, + "share_error_pp": -1.7388924664446983, + "state": "AR", + "state_fips": "05", + "target": 139258.0, + "target_share": 0.06635535839364931 + }, + { + "calibrated_relative_error": 6.961098364399732e-13, + "category": "high_school_graduate_includes_equivalency", + "estimate": 773879.365111163, + "estimate_share": 0.36881196836294583, + "households": 384, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.05.high_school_graduate_includes_equivalency.population", + "records": 538, + "relative_error": 0.11296703020315957, + "share_error_pp": 3.7492608959132925, + "state": "AR", + "state_fips": "05", + "target": 695330.0, + "target_share": 0.3313193594038129 + }, + { + "calibrated_relative_error": 2.1382895454280515e-13, + "category": "some_college_no_degree", + "estimate": 315503.4137912381, + "estimate_share": 0.15036120655428112, + "households": 230, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.05.some_college_no_degree.population", + "records": 273, + "relative_error": -0.2560495982210509, + "share_error_pp": -5.171534669134586, + "state": "AR", + "state_fips": "05", + "target": 424092.0, + "target_share": 0.20207655324562698 + }, + { + "calibrated_relative_error": 4.882760862301438e-13, + "category": "associates_degree", + "estimate": 236995.46630763283, + "estimate_share": 0.11294623989548659, + "households": 160, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.05.associates_degree.population", + "records": 179, + "relative_error": 0.27786536491374414, + "share_error_pp": 2.4575033369448676, + "state": "AR", + "state_fips": "05", + "target": 185462.0, + "target_share": 0.08837120652603792 + }, + { + "calibrated_relative_error": 3.3217872896784684e-13, + "category": "bachelors_degree", + "estimate": 470835.3967567034, + "estimate_share": 0.22438862861764589, + "households": 287, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.05.bachelors_degree.population", + "records": 377, + "relative_error": 0.3105189820490861, + "share_error_pp": 5.319735033187442, + "state": "AR", + "state_fips": "05", + "target": 359274.0, + "target_share": 0.17119127828577146 + }, + { + "calibrated_relative_error": 0.0, + "category": "graduate_or_professional_degree", + "estimate": 159554.29088024556, + "estimate_share": 0.07603967069446875, + "households": 169, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.05.graduate_or_professional_degree.population", + "records": 191, + "relative_error": -0.23959847837884385, + "share_error_pp": -2.394222259985575, + "state": "AR", + "state_fips": "05", + "target": 209829.0, + "target_share": 0.0999818932943245 + }, + { + "calibrated_relative_error": 6.616929226765933e-14, + "category": "less_than_9th_grade", + "estimate": 1414223.4821158268, + "estimate_share": 0.051694943636886294, + "households": 209, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.06.less_than_9th_grade.population", + "records": 304, + "relative_error": -0.4084615604209437, + "share_error_pp": -3.5636036157490456, + "state": "CA", + "state_fips": "06", + "target": 2390755.0, + "target_share": 0.08733097979437675 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 1308430.7559632526, + "estimate_share": 0.04782783982705014, + "households": 205, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.06.9th_to_12th_grade_no_diploma.population", + "records": 261, + "relative_error": -0.2553884016760466, + "share_error_pp": -1.6360213889746031, + "state": "CA", + "state_fips": "06", + "target": 1757199.0, + "target_share": 0.06418805371679617 + }, + { + "calibrated_relative_error": -2.9976021664879227e-15, + "category": "high_school_graduate_includes_equivalency", + "estimate": 5949366.19969616, + "estimate_share": 0.21747068568565917, + "households": 706, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.06.high_school_graduate_includes_equivalency.population", + "records": 1015, + "relative_error": 0.06187314024272195, + "share_error_pp": 1.2811460264077812, + "state": "CA", + "state_fips": "06", + "target": 5602709.0, + "target_share": 0.20465922542158135 + }, + { + "calibrated_relative_error": 1.9984014443252818e-15, + "category": "some_college_no_degree", + "estimate": 4310760.626814052, + "estimate_share": 0.15757377136876716, + "households": 591, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.06.some_college_no_degree.population", + "records": 727, + "relative_error": -0.1490736356068102, + "share_error_pp": -2.7478827103715546, + "state": "CA", + "state_fips": "06", + "target": 5065962.0, + "target_share": 0.1850525984724827 + }, + { + "calibrated_relative_error": 4.440892098500626e-16, + "category": "associates_degree", + "estimate": 2740481.186650545, + "estimate_share": 0.10017442241158056, + "households": 376, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.06.associates_degree.population", + "records": 437, + "relative_error": 0.2911462643193343, + "share_error_pp": 2.2641769935186726, + "state": "CA", + "state_fips": "06", + "target": 2122518.0, + "target_share": 0.07753265247639383 + }, + { + "calibrated_relative_error": -5.551115123125783e-16, + "category": "bachelors_degree", + "estimate": 7389416.128758071, + "estimate_share": 0.2701096786443835, + "households": 1106, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.06.bachelors_degree.population", + "records": 1479, + "relative_error": 0.16264705599037454, + "share_error_pp": 3.7945352457691954, + "state": "CA", + "state_fips": "06", + "target": 6355683.0, + "target_share": 0.23216432618669156 + }, + { + "calibrated_relative_error": 4.440892098500626e-16, + "category": "graduate_or_professional_degree", + "estimate": 4244416.581736898, + "estimate_share": 0.15514865842567319, + "households": 799, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.06.graduate_or_professional_degree.population", + "records": 1088, + "relative_error": 0.04005116964546862, + "share_error_pp": 0.6076494493995582, + "state": "CA", + "state_fips": "06", + "target": 4080969.0, + "target_share": 0.1490721639316776 + }, + { + "calibrated_relative_error": 1.13464793116691e-13, + "category": "less_than_9th_grade", + "estimate": 144608.3294854098, + "estimate_share": 0.03448022296386058, + "households": 49, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.08.less_than_9th_grade.population", + "records": 74, + "relative_error": 0.08925443461768934, + "share_error_pp": 0.29082372955002017, + "state": "CO", + "state_fips": "08", + "target": 132759.0, + "target_share": 0.03157198566836038 + }, + { + "calibrated_relative_error": 2.3776536295372352e-12, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 115375.21290796493, + "estimate_share": 0.027509916473870136, + "households": 80, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.08.9th_to_12th_grade_no_diploma.population", + "records": 104, + "relative_error": -0.25424851071058796, + "share_error_pp": -0.9282330400180092, + "state": "CO", + "state_fips": "08", + "target": 154710.0, + "target_share": 0.03679224687405023 + }, + { + "calibrated_relative_error": 6.905587213168474e-14, + "category": "high_school_graduate_includes_equivalency", + "estimate": 846247.9041707014, + "estimate_share": 0.20177825525222934, + "households": 354, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.08.high_school_graduate_includes_equivalency.population", + "records": 463, + "relative_error": 0.05828478551087479, + "share_error_pp": 1.1612208567384152, + "state": "CO", + "state_fips": "08", + "target": 799641.0, + "target_share": 0.19016604668484519 + }, + { + "calibrated_relative_error": 2.3359092438113294e-13, + "category": "some_college_no_degree", + "estimate": 614021.9469687971, + "estimate_share": 0.14640659851010865, + "households": 217, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.08.some_college_no_degree.population", + "records": 253, + "relative_error": -0.19871858675610454, + "share_error_pp": -3.5830482348172596, + "state": "CO", + "state_fips": "08", + "target": 766300.0, + "target_share": 0.18223708085828125 + }, + { + "calibrated_relative_error": 2.19824158875781e-14, + "category": "associates_degree", + "estimate": 407642.6062549199, + "estimate_share": 0.09719777555868245, + "households": 198, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.08.associates_degree.population", + "records": 215, + "relative_error": 0.18848319870003527, + "share_error_pp": 1.5628905257357495, + "state": "CO", + "state_fips": "08", + "target": 342994.0, + "target_share": 0.08156887030132495 + }, + { + "calibrated_relative_error": 1.509903313490213e-14, + "category": "bachelors_degree", + "estimate": 1243191.549835475, + "estimate_share": 0.29642498449191657, + "households": 511, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.08.bachelors_degree.population", + "records": 667, + "relative_error": 0.01818657202906082, + "share_error_pp": 0.6057081048318258, + "state": "CO", + "state_fips": "08", + "target": 1220986.0, + "target_share": 0.2903679034435983 + }, + { + "calibrated_relative_error": 2.375877272697835e-14, + "category": "graduate_or_professional_degree", + "estimate": 822862.4035709653, + "estimate_share": 0.1962022467493322, + "households": 335, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.08.graduate_or_professional_degree.population", + "records": 408, + "relative_error": 0.044809114050480714, + "share_error_pp": 0.8906380579792511, + "state": "CO", + "state_fips": "08", + "target": 787572.0, + "target_share": 0.1872958661695397 + }, + { + "calibrated_relative_error": -4.440892098500626e-16, + "category": "less_than_9th_grade", + "estimate": 96854.63072237566, + "estimate_share": 0.037239529561971796, + "households": 51, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.09.less_than_9th_grade.population", + "records": 67, + "relative_error": -0.0025269750527738832, + "share_error_pp": -0.002048200359718727, + "state": "CT", + "state_fips": "09", + "target": 97100.0, + "target_share": 0.03726001156556898 + }, + { + "calibrated_relative_error": 2.6645352591003757e-15, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 67893.84223726053, + "estimate_share": 0.026104428112658208, + "households": 68, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.09.9th_to_12th_grade_no_diploma.population", + "records": 85, + "relative_error": -0.4160422978776026, + "share_error_pp": -1.8509735066238584, + "state": "CT", + "state_fips": "09", + "target": 116265.0, + "target_share": 0.04461416317889679 + }, + { + "calibrated_relative_error": 1.1102230246251565e-15, + "category": "high_school_graduate_includes_equivalency", + "estimate": 668365.7009382327, + "estimate_share": 0.25697918718663015, + "households": 352, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.09.high_school_graduate_includes_equivalency.population", + "records": 495, + "relative_error": 0.01119069266218653, + "share_error_pp": 0.3346719787221619, + "state": "CT", + "state_fips": "09", + "target": 660969.0, + "target_share": 0.25363246739940853 + }, + { + "calibrated_relative_error": 6.8833827526759706e-15, + "category": "some_college_no_degree", + "estimate": 255704.73716465652, + "estimate_share": 0.09831563083518707, + "households": 162, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.09.some_college_no_degree.population", + "records": 178, + "relative_error": -0.39296128944157627, + "share_error_pp": -6.332336454894599, + "state": "CT", + "state_fips": "09", + "target": 421233.0, + "target_share": 0.16163899538413307 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "associates_degree", + "estimate": 259301.43725630123, + "estimate_share": 0.09969852206495465, + "households": 143, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.09.associates_degree.population", + "records": 152, + "relative_error": 0.2888642214483177, + "share_error_pp": 2.249777348791487, + "state": "CT", + "state_fips": "09", + "target": 201186.0, + "target_share": 0.07720074857703978 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 724037.7687917948, + "estimate_share": 0.2783844788195254, + "households": 331, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.09.bachelors_degree.population", + "records": 421, + "relative_error": 0.19390311551530526, + "share_error_pp": 4.567402594730035, + "state": "CT", + "state_fips": "09", + "target": 606446.0, + "target_share": 0.23271045287222503 + }, + { + "calibrated_relative_error": 0.0, + "category": "graduate_or_professional_degree", + "estimate": 528697.2605384431, + "estimate_share": 0.20327822341907265, + "households": 285, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.09.graduate_or_professional_degree.population", + "records": 355, + "relative_error": 0.05148099197800193, + "share_error_pp": 1.0335062396344796, + "state": "CT", + "state_fips": "09", + "target": 502812.0, + "target_share": 0.19294316102272785 + }, + { + "calibrated_relative_error": 0.0, + "category": "less_than_9th_grade", + "estimate": 17182.616143069426, + "estimate_share": 0.02298013787453692, + "households": 58, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.10.less_than_9th_grade.population", + "records": 89, + "relative_error": -0.2538057001316095, + "share_error_pp": -0.7857763267939889, + "state": "DE", + "state_fips": "10", + "target": 23027.0, + "target_share": 0.03083790114247681 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 24979.54172627026, + "estimate_share": 0.033407794723038946, + "households": 78, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.10.9th_to_12th_grade_no_diploma.population", + "records": 94, + "relative_error": -0.34323127395829356, + "share_error_pp": -1.752757384659509, + "state": "DE", + "state_fips": "10", + "target": 38034.0, + "target_share": 0.050935368569634036 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 244488.27034386666, + "estimate_share": 0.3269801358785095, + "households": 411, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.10.high_school_graduate_includes_equivalency.population", + "records": 560, + "relative_error": 0.1307855305413077, + "share_error_pp": 3.7429024404324718, + "state": "DE", + "state_fips": "10", + "target": 216211.0, + "target_share": 0.2895511114741848 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "some_college_no_degree", + "estimate": 107513.09310215301, + "estimate_share": 0.14378868050322702, + "households": 222, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.10.some_college_no_degree.population", + "records": 278, + "relative_error": -0.22847275511368403, + "share_error_pp": -4.2831042522146925, + "state": "DE", + "state_fips": "10", + "target": 139351.0, + "target_share": 0.18661972302537394 + }, + { + "calibrated_relative_error": 0.0, + "category": "associates_degree", + "estimate": 69981.42958643634, + "estimate_share": 0.09359359990138415, + "households": 171, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.10.associates_degree.population", + "records": 200, + "relative_error": 0.14097056470916014, + "share_error_pp": 1.1453387690769867, + "state": "DE", + "state_fips": "10", + "target": 61335.0, + "target_share": 0.08214021221061428 + }, + { + "calibrated_relative_error": 0.0, + "category": "bachelors_degree", + "estimate": 149160.26315048474, + "estimate_share": 0.19948786518069972, + "households": 356, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.10.bachelors_degree.population", + "records": 451, + "relative_error": -0.00012559977956183577, + "share_error_pp": -0.029357636763691075, + "state": "DE", + "state_fips": "10", + "target": 149179.0, + "target_share": 0.19978144154833663 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "graduate_or_professional_degree", + "estimate": 134410.75862291304, + "estimate_share": 0.17976178593860379, + "households": 306, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.10.graduate_or_professional_degree.population", + "records": 389, + "relative_error": 0.12408013968683029, + "share_error_pp": 1.9627543909224276, + "state": "DE", + "state_fips": "10", + "target": 119574.0, + "target_share": 0.1601342420293795 + }, + { + "calibrated_relative_error": 1.9095836023552692e-14, + "category": "less_than_9th_grade", + "estimate": 8563.695622255955, + "estimate_share": 0.017754053527940135, + "households": 15, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.11.less_than_9th_grade.population", + "records": 22, + "relative_error": -0.4617751478690243, + "share_error_pp": -1.3980865853277804, + "state": "DC", + "state_fips": "11", + "target": 15911.0, + "target_share": 0.03173491938121794 + }, + { + "calibrated_relative_error": 0.0, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 21058.232605115885, + "estimate_share": 0.04365743545384819, + "households": 26, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.11.9th_to_12th_grade_no_diploma.population", + "records": 26, + "relative_error": -0.13819387742517353, + "share_error_pp": -0.5078832227633827, + "state": "DC", + "state_fips": "11", + "target": 24435.0, + "target_share": 0.048736267681482016 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 75889.24976479168, + "estimate_share": 0.1573318181717902, + "households": 77, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.11.high_school_graduate_includes_equivalency.population", + "records": 95, + "relative_error": 0.059520980716383454, + "share_error_pp": 1.4471825990336113, + "state": "DC", + "state_fips": "11", + "target": 71626.0, + "target_share": 0.1428599921814541 + }, + { + "calibrated_relative_error": 0.0, + "category": "some_college_no_degree", + "estimate": 46693.70990589758, + "estimate_share": 0.09680430758572757, + "households": 58, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.11.some_college_no_degree.population", + "records": 68, + "relative_error": -0.08604991376203597, + "share_error_pp": -0.5096077756892275, + "state": "DC", + "state_fips": "11", + "target": 51090.0, + "target_share": 0.10190038534261985 + }, + { + "calibrated_relative_error": 0.0, + "category": "associates_degree", + "estimate": 17416.38364529262, + "estimate_share": 0.03610723934396561, + "households": 20, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.11.associates_degree.population", + "records": 21, + "relative_error": 0.7266167983833269, + "share_error_pp": 1.5988445314781694, + "state": "DC", + "state_fips": "11", + "target": 10087.0, + "target_share": 0.020118794029183918 + }, + { + "calibrated_relative_error": 0.0, + "category": "bachelors_degree", + "estimate": 118611.77726376745, + "estimate_share": 0.24590316324557707, + "households": 177, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.11.bachelors_degree.population", + "records": 228, + "relative_error": -0.12805974135668485, + "share_error_pp": -2.541633604836038, + "state": "DC", + "state_fips": "11", + "target": 136032.0, + "target_share": 0.27131949929393745 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "graduate_or_professional_degree", + "estimate": 194118.52283700998, + "estimate_share": 0.4024419826711512, + "households": 299, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.11.graduate_or_professional_degree.population", + "records": 422, + "relative_error": 0.01002920447372646, + "share_error_pp": 1.911184058104648, + "state": "DC", + "state_fips": "11", + "target": 192191.0, + "target_share": 0.38333014209010474 + }, + { + "calibrated_relative_error": 1.176836406102666e-14, + "category": "less_than_9th_grade", + "estimate": 423565.6631107128, + "estimate_share": 0.024959673167755592, + "households": 71, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.12.less_than_9th_grade.population", + "records": 96, + "relative_error": -0.39716939388878214, + "share_error_pp": -1.6434804430423504, + "state": "FL", + "state_fips": "12", + "target": 702628.0, + "target_share": 0.041394477598179096 + }, + { + "calibrated_relative_error": -6.661338147750939e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 709234.8993785002, + "estimate_share": 0.041793452183177364, + "households": 103, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.12.9th_to_12th_grade_no_diploma.population", + "records": 128, + "relative_error": -0.24052588812068298, + "share_error_pp": -1.3223189489314404, + "state": "FL", + "state_fips": "12", + "target": 933850.0, + "target_share": 0.05501664167249177 + }, + { + "calibrated_relative_error": -6.661338147750939e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 5027595.561936247, + "estimate_share": 0.2962637271491647, + "households": 640, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.12.high_school_graduate_includes_equivalency.population", + "records": 921, + "relative_error": 0.11997096082130843, + "share_error_pp": 3.179731375287609, + "state": "FL", + "state_fips": "12", + "target": 4489041.0, + "target_share": 0.2644664133962886 + }, + { + "calibrated_relative_error": 4.218847493575595e-15, + "category": "some_college_no_degree", + "estimate": 2006868.8119638297, + "estimate_share": 0.11825979771189873, + "households": 301, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.12.some_college_no_degree.population", + "records": 362, + "relative_error": -0.3403667656026179, + "share_error_pp": -6.097957225226105, + "state": "FL", + "state_fips": "12", + "target": 3042401.0, + "target_share": 0.1792393699641598 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "associates_degree", + "estimate": 2031714.2617782135, + "estimate_share": 0.11972387839898409, + "households": 326, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.12.associates_degree.population", + "records": 367, + "relative_error": 0.1790466147423686, + "share_error_pp": 1.8204580156470778, + "state": "FL", + "state_fips": "12", + "target": 1723184.0, + "target_share": 0.10151929824251331 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "bachelors_degree", + "estimate": 4420469.727647918, + "estimate_share": 0.26048730872032544, + "households": 612, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.12.bachelors_degree.population", + "records": 780, + "relative_error": 0.17617861531336731, + "share_error_pp": 3.9069731025557193, + "state": "FL", + "state_fips": "12", + "target": 3758332.0, + "target_share": 0.22141757769476825 + }, + { + "calibrated_relative_error": -4.440892098500626e-16, + "category": "graduate_or_professional_degree", + "estimate": 2350551.4529515738, + "estimate_share": 0.13851216266869407, + "households": 359, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.12.graduate_or_professional_degree.population", + "records": 444, + "relative_error": 0.011199070840708814, + "share_error_pp": 0.15659412370948866, + "state": "FL", + "state_fips": "12", + "target": 2324519.0, + "target_share": 0.13694622143159918 + }, + { + "calibrated_relative_error": -1.6653345369377348e-15, + "category": "less_than_9th_grade", + "estimate": 227004.26151002717, + "estimate_share": 0.029977242452102017, + "households": 68, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.13.less_than_9th_grade.population", + "records": 88, + "relative_error": -0.2836903406981611, + "share_error_pp": -1.1782912197567594, + "state": "GA", + "state_fips": "13", + "target": 316908.0, + "target_share": 0.04176015464966961 + }, + { + "calibrated_relative_error": -2.55351295663786e-15, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 508891.6170625908, + "estimate_share": 0.06720211896045702, + "households": 107, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.13.9th_to_12th_grade_no_diploma.population", + "records": 143, + "relative_error": 0.10958109748206812, + "share_error_pp": 0.6766198227636862, + "state": "GA", + "state_fips": "13", + "target": 458634.0, + "target_share": 0.06043592073282016 + }, + { + "calibrated_relative_error": -2.8754776337791554e-14, + "category": "high_school_graduate_includes_equivalency", + "estimate": 2449666.717699366, + "estimate_share": 0.3234928394508362, + "households": 451, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.13.high_school_graduate_includes_equivalency.population", + "records": 656, + "relative_error": 0.2301914577438866, + "share_error_pp": 6.1093226338557685, + "state": "GA", + "state_fips": "13", + "target": 1991289.0, + "target_share": 0.2623996131122785 + }, + { + "calibrated_relative_error": 6.352696146905146e-13, + "category": "some_college_no_degree", + "estimate": 829665.380957395, + "estimate_share": 0.10956217347477776, + "households": 223, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.13.some_college_no_degree.population", + "records": 276, + "relative_error": -0.41893876369116045, + "share_error_pp": -7.859031246990495, + "state": "GA", + "state_fips": "13", + "target": 1427845.0, + "target_share": 0.1881524859446827 + }, + { + "calibrated_relative_error": -1.7541523789077473e-14, + "category": "associates_degree", + "estimate": 735769.5618937465, + "estimate_share": 0.0971626805551906, + "households": 197, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.13.associates_degree.population", + "records": 220, + "relative_error": 0.15218374613599472, + "share_error_pp": 1.3013678708381535, + "state": "GA", + "state_fips": "13", + "target": 638587.0, + "target_share": 0.08414900184680907 + }, + { + "calibrated_relative_error": -4.529709940470639e-14, + "category": "bachelors_degree", + "estimate": 1708808.1458922126, + "estimate_share": 0.22565812532675764, + "households": 411, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.13.bachelors_degree.population", + "records": 545, + "relative_error": 0.04532928565359229, + "share_error_pp": 1.0246526733310612, + "state": "GA", + "state_fips": "13", + "target": 1634708.0, + "target_share": 0.21541159859344702 + }, + { + "calibrated_relative_error": -1.432187701766452e-14, + "category": "graduate_or_professional_degree", + "estimate": 1112747.4566799724, + "estimate_share": 0.1469448197798788, + "households": 269, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.13.graduate_or_professional_degree.population", + "records": 351, + "relative_error": -0.007179324050653024, + "share_error_pp": -0.07464053404141469, + "state": "GA", + "state_fips": "13", + "target": 1120794.0, + "target_share": 0.14769122512029295 + }, + { + "calibrated_relative_error": 2.6645352591003757e-15, + "category": "less_than_9th_grade", + "estimate": 25562.4294693489, + "estimate_share": 0.024680288699432843, + "households": 30, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.15.less_than_9th_grade.population", + "records": 43, + "relative_error": 0.05564441335324788, + "share_error_pp": 0.1328668165436298, + "state": "HI", + "state_fips": "15", + "target": 24215.0, + "target_share": 0.023351620533996545 + }, + { + "calibrated_relative_error": 4.6407322429331543e-14, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 18389.87440833914, + "estimate_share": 0.017755253274667798, + "households": 35, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.15.9th_to_12th_grade_no_diploma.population", + "records": 54, + "relative_error": -0.5514008291862433, + "share_error_pp": -2.1777116420589455, + "state": "HI", + "state_fips": "15", + "target": 40994.0, + "target_share": 0.03953236969525725 + }, + { + "calibrated_relative_error": 1.1102230246251565e-15, + "category": "high_school_graduate_includes_equivalency", + "estimate": 334092.9971234043, + "estimate_share": 0.3225636918177647, + "households": 312, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.15.high_school_graduate_includes_equivalency.population", + "records": 546, + "relative_error": 0.18651091401044217, + "share_error_pp": 5.102721015430767, + "state": "HI", + "state_fips": "15", + "target": 281576.0, + "target_share": 0.271536481663457 + }, + { + "calibrated_relative_error": 1.3322676295501878e-15, + "category": "some_college_no_degree", + "estimate": 91239.62150038953, + "estimate_share": 0.08809100880480394, + "households": 194, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.15.some_college_no_degree.population", + "records": 240, + "relative_error": -0.5276865578519612, + "share_error_pp": -9.819735164431092, + "state": "HI", + "state_fips": "15", + "target": 193176.0, + "target_share": 0.18628836044911487 + }, + { + "calibrated_relative_error": 1.3322676295501878e-15, + "category": "associates_degree", + "estimate": 129901.95763799574, + "estimate_share": 0.1254191359616841, + "households": 217, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.15.associates_degree.population", + "records": 262, + "relative_error": 0.2315666698711163, + "share_error_pp": 2.370289069782477, + "state": "HI", + "state_fips": "15", + "target": 105477.0, + "target_share": 0.10171624526385933 + }, + { + "calibrated_relative_error": 8.881784197001252e-16, + "category": "bachelors_degree", + "estimate": 260658.60820059164, + "estimate_share": 0.25166347001941725, + "households": 382, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.15.bachelors_degree.population", + "records": 524, + "relative_error": 0.053395925578072045, + "share_error_pp": 1.304009216869212, + "state": "HI", + "state_fips": "15", + "target": 247446.0, + "target_share": 0.23862337785072513 + }, + { + "calibrated_relative_error": 4.440892098500626e-16, + "category": "graduate_or_professional_degree", + "estimate": 175897.23657936533, + "estimate_share": 0.16982715142222943, + "households": 231, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.15.graduate_or_professional_degree.population", + "records": 309, + "relative_error": 0.2207540935072443, + "share_error_pp": 3.0875606878639577, + "state": "HI", + "state_fips": "15", + "target": 144089.0, + "target_share": 0.13895154454358985 + }, + { + "calibrated_relative_error": 7.038813976123492e-14, + "category": "less_than_9th_grade", + "estimate": 34898.29452833313, + "estimate_share": 0.026165114540831782, + "households": 46, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.16.less_than_9th_grade.population", + "records": 61, + "relative_error": -0.1019712686669636, + "share_error_pp": -0.2935376919824033, + "state": "ID", + "state_fips": "16", + "target": 38861.0, + "target_share": 0.029100491460655815 + }, + { + "calibrated_relative_error": 2.4424906541753444e-15, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 56850.28187431348, + "estimate_share": 0.04262369141598947, + "households": 61, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.16.9th_to_12th_grade_no_diploma.population", + "records": 72, + "relative_error": -0.07461207353723542, + "share_error_pp": -0.3380260937113369, + "state": "ID", + "state_fips": "16", + "target": 61434.0, + "target_share": 0.04600395235310284 + }, + { + "calibrated_relative_error": 9.903189379656396e-14, + "category": "high_school_graduate_includes_equivalency", + "estimate": 351136.47001978033, + "estimate_share": 0.2632657578745504, + "households": 255, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.16.high_school_graduate_includes_equivalency.population", + "records": 351, + "relative_error": -0.00029760187512184455, + "share_error_pp": 0.024407235096096658, + "state": "ID", + "state_fips": "16", + "target": 351241.0, + "target_share": 0.26302168552358945 + }, + { + "calibrated_relative_error": 7.260858581048524e-14, + "category": "some_college_no_degree", + "estimate": 276188.45930300734, + "estimate_share": 0.20707323295274535, + "households": 228, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.16.some_college_no_degree.population", + "records": 293, + "relative_error": -0.11097658473594596, + "share_error_pp": -2.5563708444147126, + "state": "ID", + "state_fips": "16", + "target": 310665.0, + "target_share": 0.23263694139689248 + }, + { + "calibrated_relative_error": 3.510525203864745e-13, + "category": "associates_degree", + "estimate": 146727.65080504902, + "estimate_share": 0.11000955323201717, + "households": 146, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.16.associates_degree.population", + "records": 170, + "relative_error": 0.11016858069751922, + "share_error_pp": 1.1038228384985513, + "state": "ID", + "state_fips": "16", + "target": 132167.0, + "target_share": 0.09897132484703165 + }, + { + "calibrated_relative_error": 3.04867242562068e-13, + "category": "bachelors_degree", + "estimate": 354183.90956669947, + "estimate_share": 0.26555058599807563, + "households": 248, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.16.bachelors_degree.population", + "records": 314, + "relative_error": 0.21500162796585864, + "share_error_pp": 4.725833502140708, + "state": "ID", + "state_fips": "16", + "target": 291509.0, + "target_share": 0.21829225097666854 + }, + { + "calibrated_relative_error": 2.2861712523081223e-12, + "category": "graduate_or_professional_degree", + "estimate": 113786.83365402391, + "estimate_share": 0.08531206398579022, + "households": 135, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.16.graduate_or_professional_degree.population", + "records": 164, + "relative_error": -0.23903675747994446, + "share_error_pp": -2.6661289456269013, + "state": "ID", + "state_fips": "16", + "target": 149530.0, + "target_share": 0.11197335344205923 + }, + { + "calibrated_relative_error": 1.5543122344752192e-15, + "category": "less_than_9th_grade", + "estimate": 401568.23469167924, + "estimate_share": 0.04544078936351563, + "households": 78, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.17.less_than_9th_grade.population", + "records": 128, + "relative_error": -0.011151929978110542, + "share_error_pp": -0.044873956529439124, + "state": "IL", + "state_fips": "17", + "target": 406097.0, + "target_share": 0.04588952892881002 + }, + { + "calibrated_relative_error": 2.886579864025407e-15, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 401251.00335347326, + "estimate_share": 0.04540489199621019, + "households": 102, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.17.9th_to_12th_grade_no_diploma.population", + "records": 125, + "relative_error": -0.033740136700508905, + "share_error_pp": -0.152029474990098, + "state": "IL", + "state_fips": "17", + "target": 415262.0, + "target_share": 0.04692518674611117 + }, + { + "calibrated_relative_error": -1.5987211554602254e-14, + "category": "high_school_graduate_includes_equivalency", + "estimate": 2265617.2291460996, + "estimate_share": 0.2563734538590312, + "households": 536, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.17.high_school_graduate_includes_equivalency.population", + "records": 723, + "relative_error": 0.04020632674704738, + "share_error_pp": 1.025120985013936, + "state": "IL", + "state_fips": "17", + "target": 2178046.0, + "target_share": 0.24612224400889185 + }, + { + "calibrated_relative_error": 3.5771385853422544e-13, + "category": "some_college_no_degree", + "estimate": 1303579.2052200078, + "estimate_share": 0.14751084116138355, + "households": 377, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.17.some_college_no_degree.population", + "records": 467, + "relative_error": -0.19485180848086825, + "share_error_pp": -3.5444638095627727, + "state": "IL", + "state_fips": "17", + "target": 1619055.0, + "target_share": 0.18295547925701128 + }, + { + "calibrated_relative_error": 1.3211653993039363e-13, + "category": "associates_degree", + "estimate": 955272.8826771582, + "estimate_share": 0.10809708063622038, + "households": 264, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.17.associates_degree.population", + "records": 301, + "relative_error": 0.2581249450826084, + "share_error_pp": 2.229703977491468, + "state": "IL", + "state_fips": "17", + "target": 759283.0, + "target_share": 0.0858000408613057 + }, + { + "calibrated_relative_error": -8.992806499463768e-15, + "category": "bachelors_degree", + "estimate": 2117906.8930245256, + "estimate_share": 0.23965879943506257, + "households": 637, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.17.bachelors_degree.population", + "records": 800, + "relative_error": 0.02643545798555147, + "share_error_pp": 0.6496120813751949, + "state": "IL", + "state_fips": "17", + "target": 2063361.0, + "target_share": 0.23316267862131063 + }, + { + "calibrated_relative_error": -3.4416913763379853e-15, + "category": "graduate_or_professional_degree", + "estimate": 1391980.1449258958, + "estimate_share": 0.15751414354857643, + "households": 434, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.17.graduate_or_professional_degree.population", + "records": 557, + "relative_error": -0.011619217374522206, + "share_error_pp": -0.16306980279829353, + "state": "IL", + "state_fips": "17", + "target": 1408344.0, + "target_share": 0.15914484157655936 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "less_than_9th_grade", + "estimate": 111246.76446091455, + "estimate_share": 0.02383822920443355, + "households": 46, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.18.less_than_9th_grade.population", + "records": 68, + "relative_error": -0.3679089281644419, + "share_error_pp": -1.372330785673974, + "state": "IN", + "state_fips": "18", + "target": 175998.0, + "target_share": 0.03756153706117329 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 288860.95408009226, + "estimate_share": 0.06189783284880971, + "households": 108, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.18.9th_to_12th_grade_no_diploma.population", + "records": 136, + "relative_error": 0.08815246771676422, + "share_error_pp": 0.524329343211713, + "state": "IN", + "state_fips": "18", + "target": 265460.0, + "target_share": 0.05665453941669258 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1628604.7719844952, + "estimate_share": 0.34898142005416016, + "households": 497, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.18.high_school_graduate_includes_equivalency.population", + "records": 684, + "relative_error": 0.08471182355367968, + "share_error_pp": 2.8548629398723104, + "state": "IN", + "state_fips": "18", + "target": 1501417.0, + "target_share": 0.32043279065543706 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "some_college_no_degree", + "estimate": 732709.4342923664, + "estimate_share": 0.15700677246257308, + "households": 257, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.18.some_college_no_degree.population", + "records": 299, + "relative_error": -0.15914288730070048, + "share_error_pp": -2.8964218176601357, + "state": "IN", + "state_fips": "18", + "target": 871384.0, + "target_share": 0.18597099063917444 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "associates_degree", + "estimate": 512947.1145339655, + "estimate_share": 0.10991556424375466, + "households": 195, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.18.associates_degree.population", + "records": 214, + "relative_error": 0.17944634928079806, + "share_error_pp": 1.7098030660477757, + "state": "IN", + "state_fips": "18", + "target": 434905.0, + "target_share": 0.0928175335832769 + }, + { + "calibrated_relative_error": 0.0, + "category": "bachelors_degree", + "estimate": 988715.3134873707, + "estimate_share": 0.21186433938153884, + "households": 344, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.18.bachelors_degree.population", + "records": 421, + "relative_error": 0.0844125524126853, + "share_error_pp": 1.727800011291722, + "state": "IN", + "state_fips": "18", + "target": 911752.0, + "target_share": 0.19458633926862162 + }, + { + "calibrated_relative_error": 0.0, + "category": "graduate_or_professional_degree", + "estimate": 403653.4113997741, + "estimate_share": 0.08649584180473, + "households": 202, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.18.graduate_or_professional_degree.population", + "records": 261, + "relative_error": -0.23066010120593872, + "share_error_pp": -2.548042757089412, + "state": "IN", + "state_fips": "18", + "target": 524675.0, + "target_share": 0.11197626937562412 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "less_than_9th_grade", + "estimate": 79114.1135172, + "estimate_share": 0.03621592636920254, + "households": 37, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.19.less_than_9th_grade.population", + "records": 54, + "relative_error": 0.31464652980607855, + "share_error_pp": 0.8766686412881218, + "state": "IA", + "state_fips": "19", + "target": 60179.0, + "target_share": 0.02744923995632132 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 79514.17966808272, + "estimate_share": 0.03639906393618076, + "households": 52, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.19.9th_to_12th_grade_no_diploma.population", + "records": 57, + "relative_error": -0.15036245092126255, + "share_error_pp": -0.6287995844677797, + "state": "IA", + "state_fips": "19", + "target": 93586.0, + "target_share": 0.04268705978085856 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 638950.4435578864, + "estimate_share": 0.2924912027539924, + "households": 357, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.19.high_school_graduate_includes_equivalency.population", + "records": 486, + "relative_error": 0.004332709138857638, + "share_error_pp": 0.23062251908576026, + "state": "IA", + "state_fips": "19", + "target": 636194.0, + "target_share": 0.29018497756313477 + }, + { + "calibrated_relative_error": 0.0, + "category": "some_college_no_degree", + "estimate": 366604.7640529426, + "estimate_share": 0.1678200077240799, + "households": 206, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.19.some_college_no_degree.population", + "records": 240, + "relative_error": -0.14755567427808802, + "share_error_pp": -2.8343146920155076, + "state": "IA", + "state_fips": "19", + "target": 430063.0, + "target_share": 0.19616315464423498 + }, + { + "calibrated_relative_error": 0.0, + "category": "associates_degree", + "estimate": 245050.15600124322, + "estimate_share": 0.11217617201225656, + "households": 225, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.19.associates_degree.population", + "records": 256, + "relative_error": -0.09132651781843149, + "share_error_pp": -1.0831581226926166, + "state": "IA", + "state_fips": "19", + "target": 269679.0, + "target_share": 0.12300775323918273 + }, + { + "calibrated_relative_error": 0.0, + "category": "bachelors_degree", + "estimate": 528540.6010637572, + "estimate_share": 0.24194908645595273, + "households": 318, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.19.bachelors_degree.population", + "records": 415, + "relative_error": 0.14084673262367509, + "share_error_pp": 3.063112702019952, + "state": "IA", + "state_fips": "19", + "target": 463288.0, + "target_share": 0.2113179594357532 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "graduate_or_professional_degree", + "estimate": 246737.4045128601, + "estimate_share": 0.11294854074833523, + "households": 164, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.19.graduate_or_professional_degree.population", + "records": 211, + "relative_error": 0.03071372271804873, + "share_error_pp": 0.37586853678207716, + "state": "IA", + "state_fips": "19", + "target": 239385.0, + "target_share": 0.10918985538051446 + }, + { + "calibrated_relative_error": 8.881784197001252e-16, + "category": "less_than_9th_grade", + "estimate": 46013.2231711951, + "estimate_share": 0.023345380452625956, + "households": 35, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.20.less_than_9th_grade.population", + "records": 57, + "relative_error": -0.32865633914712644, + "share_error_pp": -1.1156489642464475, + "state": "KS", + "state_fips": "20", + "target": 68539.0, + "target_share": 0.03450187009509043 + }, + { + "calibrated_relative_error": 3.552713678800501e-14, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 50482.17378348943, + "estimate_share": 0.025612758068835166, + "households": 45, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.20.9th_to_12th_grade_no_diploma.population", + "records": 52, + "relative_error": -0.4411979877851513, + "share_error_pp": -1.9863524695583188, + "state": "KS", + "state_fips": "20", + "target": 90340.0, + "target_share": 0.045476282764418355 + }, + { + "calibrated_relative_error": -4.440892098500626e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 517635.77965677413, + "estimate_share": 0.26262894401068715, + "households": 291, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.20.high_school_graduate_includes_equivalency.population", + "records": 389, + "relative_error": 0.02584201947057485, + "share_error_pp": 0.862019508668399, + "state": "KS", + "state_fips": "20", + "target": 504596.0, + "target_share": 0.25400874892400316 + }, + { + "calibrated_relative_error": -1.5543122344752192e-15, + "category": "some_college_no_degree", + "estimate": 422601.27666794317, + "estimate_share": 0.2144120081932163, + "households": 261, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.20.some_college_no_degree.population", + "records": 299, + "relative_error": 0.014946218743409068, + "share_error_pp": 0.48113477450982267, + "state": "KS", + "state_fips": "20", + "target": 416378.0, + "target_share": 0.20960066044811806 + }, + { + "calibrated_relative_error": 0.0, + "category": "associates_degree", + "estimate": 253699.76276232308, + "estimate_share": 0.12871772664982706, + "households": 180, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.20.associates_degree.population", + "records": 202, + "relative_error": 0.33132399304333005, + "share_error_pp": 3.2790657841402324, + "state": "KS", + "state_fips": "20", + "target": 190562.0, + "target_share": 0.09592706880842473 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 428196.23630370694, + "estimate_share": 0.21725068047722526, + "households": 345, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.20.bachelors_degree.population", + "records": 428, + "relative_error": -0.03798393562005431, + "share_error_pp": -0.6809867312136092, + "state": "KS", + "state_fips": "20", + "target": 445103.0, + "target_share": 0.22406054778936135 + }, + { + "calibrated_relative_error": -4.440892098500626e-16, + "category": "graduate_or_professional_degree", + "estimate": 252349.20058116253, + "estimate_share": 0.1280325021475831, + "households": 186, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.20.graduate_or_professional_degree.population", + "records": 225, + "relative_error": -0.06886336921921343, + "share_error_pp": -0.8392319023000777, + "state": "KS", + "state_fips": "20", + "target": 271012.0, + "target_share": 0.13642482117058388 + }, + { + "calibrated_relative_error": 3.5216274341109965e-12, + "category": "less_than_9th_grade", + "estimate": 66805.10017524133, + "estimate_share": 0.021255019481977708, + "households": 41, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.21.less_than_9th_grade.population", + "records": 55, + "relative_error": -0.5041925176247489, + "share_error_pp": -2.157162826646071, + "state": "KY", + "state_fips": "21", + "target": 134740.0, + "target_share": 0.04282664774843842 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 215133.1325236118, + "estimate_share": 0.06844775190836308, + "households": 76, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.21.9th_to_12th_grade_no_diploma.population", + "records": 87, + "relative_error": 0.015209912338312481, + "share_error_pp": 0.10928838337632141, + "state": "KY", + "state_fips": "21", + "target": 211910.0, + "target_share": 0.06735486807459987 + }, + { + "calibrated_relative_error": -1.3322676295501878e-15, + "category": "high_school_graduate_includes_equivalency", + "estimate": 962264.0098298786, + "estimate_share": 0.3061583654853965, + "households": 341, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.21.high_school_graduate_includes_equivalency.population", + "records": 474, + "relative_error": -0.04842691379364972, + "share_error_pp": -1.5259217532950897, + "state": "KY", + "state_fips": "21", + "target": 1011235.0, + "target_share": 0.3214175830183474 + }, + { + "calibrated_relative_error": -6.217248937900877e-15, + "category": "some_college_no_degree", + "estimate": 444454.4414037996, + "estimate_share": 0.14140967959195422, + "households": 199, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.21.some_college_no_degree.population", + "records": 224, + "relative_error": -0.27747785246064804, + "share_error_pp": -5.411141715672957, + "state": "KY", + "state_fips": "21", + "target": 615143.0, + "target_share": 0.1955210967486838 + }, + { + "calibrated_relative_error": 1.9984014443252818e-15, + "category": "associates_degree", + "estimate": 522724.92993858963, + "estimate_share": 0.1663125800337896, + "households": 152, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.21.associates_degree.population", + "records": 177, + "relative_error": 0.7781271534606331, + "share_error_pp": 7.287363263994082, + "state": "KY", + "state_fips": "21", + "target": 293975.0, + "target_share": 0.09343894739384878 + }, + { + "calibrated_relative_error": -7.438494264988549e-15, + "category": "bachelors_degree", + "estimate": 513886.3084629919, + "estimate_share": 0.1635004433681031, + "households": 184, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.21.bachelors_degree.population", + "records": 223, + "relative_error": 0.011354291360044844, + "share_error_pp": 0.19971943403957748, + "state": "KY", + "state_fips": "21", + "target": 508117.0, + "target_share": 0.16150324902770732 + }, + { + "calibrated_relative_error": -8.881784197001252e-16, + "category": "graduate_or_professional_degree", + "estimate": 417759.0803880385, + "estimate_share": 0.13291616013041588, + "households": 143, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.21.graduate_or_professional_degree.population", + "records": 175, + "relative_error": 0.12587745218470325, + "share_error_pp": 1.4978552142041441, + "state": "KY", + "state_fips": "21", + "target": 371052.0, + "target_share": 0.11793760798837444 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "less_than_9th_grade", + "estimate": 61132.35258114035, + "estimate_share": 0.019664805796595557, + "households": 36, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.22.less_than_9th_grade.population", + "records": 50, + "relative_error": -0.5349666617388036, + "share_error_pp": -2.2517109931985706, + "state": "LA", + "state_fips": "22", + "target": 131458.0, + "target_share": 0.042181915728581265 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 256766.19754907445, + "estimate_share": 0.08259550298233674, + "households": 107, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.22.9th_to_12th_grade_no_diploma.population", + "records": 125, + "relative_error": 0.09110849438257751, + "share_error_pp": 0.7084682030062142, + "state": "LA", + "state_fips": "22", + "target": 235326.0, + "target_share": 0.0755108209522746 + }, + { + "calibrated_relative_error": 0.0, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1131696.433772467, + "estimate_share": 0.36403949220336385, + "households": 432, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.22.high_school_graduate_includes_equivalency.population", + "records": 579, + "relative_error": 0.10507193562739614, + "share_error_pp": 3.5431080206908883, + "state": "LA", + "state_fips": "22", + "target": 1024093.0, + "target_share": 0.32860841199645496 + }, + { + "calibrated_relative_error": 0.0, + "category": "some_college_no_degree", + "estimate": 547976.0007862811, + "estimate_share": 0.17627068453409586, + "households": 245, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.22.some_college_no_degree.population", + "records": 293, + "relative_error": -0.12490178542820829, + "share_error_pp": -2.4658961788294906, + "state": "LA", + "state_fips": "22", + "target": 626188.0, + "target_share": 0.20092964632239077 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "associates_degree", + "estimate": 343457.58177411696, + "estimate_share": 0.11048203381330364, + "households": 172, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.22.associates_degree.population", + "records": 189, + "relative_error": 0.4811995177382804, + "share_error_pp": 3.607759851600742, + "state": "LA", + "state_fips": "22", + "target": 231878.0, + "target_share": 0.07440443529729622 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 481599.66374096205, + "estimate_share": 0.15491901520723514, + "households": 272, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.22.bachelors_degree.population", + "records": 326, + "relative_error": -0.10654385889289641, + "share_error_pp": -1.8043589085977585, + "state": "LA", + "state_fips": "22", + "target": 539030.0, + "target_share": 0.17296260429321272 + }, + { + "calibrated_relative_error": 0.0, + "category": "graduate_or_professional_degree", + "estimate": 286090.6258816766, + "estimate_share": 0.09202846546306923, + "households": 169, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.22.graduate_or_professional_degree.population", + "records": 203, + "relative_error": -0.12904969882070316, + "share_error_pp": -1.3373699946720232, + "state": "LA", + "state_fips": "22", + "target": 328481.0, + "target_share": 0.10540216540978946 + }, + { + "calibrated_relative_error": 0.0, + "category": "less_than_9th_grade", + "estimate": 17477.04084145418, + "estimate_share": 0.0167268611176881, + "households": 15, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.23.less_than_9th_grade.population", + "records": 17, + "relative_error": -0.03601539760318906, + "share_error_pp": -0.054215742483721546, + "state": "ME", + "state_fips": "23", + "target": 18130.0, + "target_share": 0.017269018542525317 + }, + { + "calibrated_relative_error": 4.440892098500626e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 37513.493993804856, + "estimate_share": 0.03590327503184977, + "households": 35, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.23.9th_to_12th_grade_no_diploma.population", + "records": 38, + "relative_error": 0.020164635967716116, + "share_error_pp": 0.08775524810642824, + "state": "ME", + "state_fips": "23", + "target": 36772.0, + "target_share": 0.03502572255078549 + }, + { + "calibrated_relative_error": 4.6629367034256575e-15, + "category": "high_school_graduate_includes_equivalency", + "estimate": 386422.7805221059, + "estimate_share": 0.36983607471883256, + "households": 324, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.23.high_school_graduate_includes_equivalency.population", + "records": 471, + "relative_error": 0.24826058333394463, + "share_error_pp": 7.496829748821926, + "state": "ME", + "state_fips": "23", + "target": 309569.0, + "target_share": 0.2948677772306133 + }, + { + "calibrated_relative_error": 2.930988785010413e-14, + "category": "some_college_no_degree", + "estimate": 141252.18224888522, + "estimate_share": 0.13518911218902216, + "households": 161, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.23.some_college_no_degree.population", + "records": 177, + "relative_error": -0.25284742851838515, + "share_error_pp": -4.488684101222335, + "state": "ME", + "state_fips": "23", + "target": 189054.0, + "target_share": 0.1800759532012455 + }, + { + "calibrated_relative_error": 3.907985046680551e-14, + "category": "associates_degree", + "estimate": 120363.08657559373, + "estimate_share": 0.1151966543484205, + "households": 137, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.23.associates_degree.population", + "records": 145, + "relative_error": 0.12784001663787214, + "share_error_pp": 1.3544715084311196, + "state": "ME", + "state_fips": "23", + "target": 106720.0, + "target_share": 0.1016519392641093 + }, + { + "calibrated_relative_error": 6.417089082333405e-14, + "category": "bachelors_degree", + "estimate": 259559.88899396086, + "estimate_share": 0.24841861126893597, + "households": 293, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.23.bachelors_degree.population", + "records": 374, + "relative_error": 0.0996343404731399, + "share_error_pp": 2.3586086458414144, + "state": "ME", + "state_fips": "23", + "target": 236042.0, + "target_share": 0.22483252481052182 + }, + { + "calibrated_relative_error": 7.684963776455334e-13, + "category": "graduate_or_professional_degree", + "estimate": 82260.33130029558, + "estimate_share": 0.07872941132525092, + "households": 173, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.23.graduate_or_professional_degree.population", + "records": 226, + "relative_error": -0.4643463482431752, + "share_error_pp": -6.754765307494835, + "state": "ME", + "state_fips": "23", + "target": 153570.0, + "target_share": 0.14627706440019927 + }, + { + "calibrated_relative_error": 0.0, + "category": "less_than_9th_grade", + "estimate": 152051.24628094517, + "estimate_share": 0.03491614861524572, + "households": 53, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.24.less_than_9th_grade.population", + "records": 83, + "relative_error": -0.14124936445097924, + "share_error_pp": -0.5656149914159976, + "state": "MD", + "state_fips": "24", + "target": 177061.0, + "target_share": 0.0405722985294057 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 131332.35067222477, + "estimate_share": 0.030158384006850652, + "households": 79, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.24.9th_to_12th_grade_no_diploma.population", + "records": 96, + "relative_error": -0.33412250206749017, + "share_error_pp": -1.503595909271246, + "state": "MD", + "state_fips": "24", + "target": 197232.0, + "target_share": 0.04519434309956311 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 949904.1733978427, + "estimate_share": 0.21813037446150585, + "households": 344, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.24.high_school_graduate_includes_equivalency.population", + "records": 479, + "relative_error": -0.05807861037919371, + "share_error_pp": -1.2954668317211149, + "state": "MD", + "state_fips": "24", + "target": 1008475.0, + "target_share": 0.231085042778717 + }, + { + "calibrated_relative_error": 6.661338147750939e-16, + "category": "some_college_no_degree", + "estimate": 513461.0946507191, + "estimate_share": 0.11790816798597972, + "households": 215, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.24.some_college_no_degree.population", + "records": 256, + "relative_error": -0.30762320163820667, + "share_error_pp": -5.202248874259988, + "state": "MD", + "state_fips": "24", + "target": 741592.0, + "target_share": 0.1699306567285796 + }, + { + "calibrated_relative_error": 8.881784197001252e-16, + "category": "associates_degree", + "estimate": 476492.31205151125, + "estimate_share": 0.1094188754682872, + "households": 148, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.24.associates_degree.population", + "records": 173, + "relative_error": 0.6462161019167973, + "share_error_pp": 4.309410551645765, + "state": "MD", + "state_fips": "24", + "target": 289447.0, + "target_share": 0.06632476995182955 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 1350867.4166823493, + "estimate_share": 0.310205201430729, + "households": 416, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.24.bachelors_degree.population", + "records": 545, + "relative_error": 0.3365251651352825, + "share_error_pp": 7.8603211919064915, + "state": "MD", + "state_fips": "24", + "target": 1010731.0, + "target_share": 0.23160198951166408 + }, + { + "calibrated_relative_error": 0.0, + "category": "graduate_or_professional_degree", + "estimate": 780645.6478176642, + "estimate_share": 0.17926284803140188, + "households": 387, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.24.graduate_or_professional_degree.population", + "records": 543, + "relative_error": -0.16912638011292214, + "share_error_pp": -3.602805136883908, + "state": "MD", + "state_fips": "24", + "target": 939548.0, + "target_share": 0.21529089940024096 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "less_than_9th_grade", + "estimate": 104572.04297143404, + "estimate_share": 0.02063829944676651, + "households": 61, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.25.less_than_9th_grade.population", + "records": 81, + "relative_error": -0.5408895646441643, + "share_error_pp": -2.4248505581353395, + "state": "MA", + "state_fips": "25", + "target": 227771.0, + "target_share": 0.044886805028119904 + }, + { + "calibrated_relative_error": -4.440892098500626e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 177525.75239810345, + "estimate_share": 0.035036416363266765, + "households": 70, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.25.9th_to_12th_grade_no_diploma.population", + "records": 85, + "relative_error": -0.1500902334490155, + "share_error_pp": -0.6126753166891035, + "state": "MA", + "state_fips": "25", + "target": 208876.0, + "target_share": 0.0411631695301578 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1254017.1869624748, + "estimate_share": 0.24749236488564347, + "households": 487, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.25.high_school_graduate_includes_equivalency.population", + "records": 691, + "relative_error": 0.11134100593812635, + "share_error_pp": 2.512225266222612, + "state": "MA", + "state_fips": "25", + "target": 1128382.0, + "target_share": 0.22237011222341735 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "some_college_no_degree", + "estimate": 582962.7573243133, + "estimate_share": 0.11505331262638202, + "households": 244, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.25.some_college_no_degree.population", + "records": 274, + "relative_error": -0.16737923753300943, + "share_error_pp": -2.292595640987924, + "state": "MA", + "state_fips": "25", + "target": 700154.0, + "target_share": 0.13797926903626126 + }, + { + "calibrated_relative_error": 0.0, + "category": "associates_degree", + "estimate": 561429.5052876645, + "estimate_share": 0.1108035180257692, + "households": 211, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.25.associates_degree.population", + "records": 233, + "relative_error": 0.5613088979019505, + "share_error_pp": 3.9939354751003715, + "state": "MA", + "state_fips": "25", + "target": 359589.0, + "target_share": 0.07086416327476548 + }, + { + "calibrated_relative_error": -3.3306690738754696e-16, + "category": "bachelors_degree", + "estimate": 1210861.569291151, + "estimate_share": 0.23897518825790698, + "households": 602, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.25.bachelors_degree.population", + "records": 773, + "relative_error": -0.07230165266316568, + "share_error_pp": -1.824673332325566, + "state": "MA", + "state_fips": "25", + "target": 1305232.0, + "target_share": 0.25722192158116264 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "graduate_or_professional_degree", + "estimate": 1175523.6029992532, + "estimate_share": 0.23200090039426496, + "households": 570, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.25.graduate_or_professional_degree.population", + "records": 797, + "relative_error": 0.027252090727786005, + "share_error_pp": 0.6486341068149382, + "state": "MA", + "state_fips": "25", + "target": 1144338.0, + "target_share": 0.22551455932611558 + }, + { + "calibrated_relative_error": 0.0, + "category": "less_than_9th_grade", + "estimate": 213919.8640920394, + "estimate_share": 0.030160839839692793, + "households": 41, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.26.less_than_9th_grade.population", + "records": 53, + "relative_error": 0.1759912487330786, + "share_error_pp": 0.4548890731871591, + "state": "MI", + "state_fips": "26", + "target": 181906.0, + "target_share": 0.025611949107821202 + }, + { + "calibrated_relative_error": 0.0, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 561052.9588527189, + "estimate_share": 0.07910358631427494, + "households": 128, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.26.9th_to_12th_grade_no_diploma.population", + "records": 163, + "relative_error": 0.5197891426671513, + "share_error_pp": 2.712599793132543, + "state": "MI", + "state_fips": "26", + "target": 369165.0, + "target_share": 0.05197758838294951 + }, + { + "calibrated_relative_error": -3.3306690738754696e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1904954.267269578, + "estimate_share": 0.2685819795226541, + "households": 560, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.26.high_school_graduate_includes_equivalency.population", + "records": 745, + "relative_error": -0.026150771189741073, + "share_error_pp": -0.6833556773025606, + "state": "MI", + "state_fips": "26", + "target": 1956108.0, + "target_share": 0.2754155362956797 + }, + { + "calibrated_relative_error": 6.661338147750939e-16, + "category": "some_college_no_degree", + "estimate": 1033775.2946740498, + "estimate_share": 0.14575332321396853, + "households": 365, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.26.some_college_no_degree.population", + "records": 430, + "relative_error": -0.3222883216997807, + "share_error_pp": -6.901824375759088, + "state": "MI", + "state_fips": "26", + "target": 1525391.0, + "target_share": 0.2147715669715594 + }, + { + "calibrated_relative_error": -3.3306690738754696e-16, + "category": "associates_degree", + "estimate": 774820.3796697329, + "estimate_share": 0.10924293297837044, + "households": 264, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.26.associates_degree.population", + "records": 307, + "relative_error": 0.1023618486835216, + "share_error_pp": 1.0280020786020485, + "state": "MI", + "state_fips": "26", + "target": 702873.0, + "target_share": 0.09896291219234996 + }, + { + "calibrated_relative_error": -3.3306690738754696e-16, + "category": "bachelors_degree", + "estimate": 1631724.349236095, + "estimate_share": 0.2300589380454277, + "households": 459, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.26.bachelors_degree.population", + "records": 567, + "relative_error": 0.1359423225563683, + "share_error_pp": 2.7810060625607784, + "state": "MI", + "state_fips": "26", + "target": 1436450.0, + "target_share": 0.20224887741981992 + }, + { + "calibrated_relative_error": 0.0, + "category": "graduate_or_professional_degree", + "estimate": 972389.0736939367, + "estimate_share": 0.1370984000856115, + "households": 350, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.26.graduate_or_professional_degree.population", + "records": 444, + "relative_error": 0.04502342698664341, + "share_error_pp": 0.6086830455791226, + "state": "MI", + "state_fips": "26", + "target": 930495.0, + "target_share": 0.13101156962982027 + }, + { + "calibrated_relative_error": 2.4202861936828413e-14, + "category": "less_than_9th_grade", + "estimate": 171603.8785578019, + "estimate_share": 0.04319361272236543, + "households": 47, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.27.less_than_9th_grade.population", + "records": 71, + "relative_error": 0.7034671976592932, + "share_error_pp": 1.789812878659725, + "state": "MN", + "state_fips": "27", + "target": 100738.0, + "target_share": 0.025295483935768182 + }, + { + "calibrated_relative_error": 3.108624468950438e-14, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 108949.61488793166, + "estimate_share": 0.027423199937378257, + "households": 47, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.27.9th_to_12th_grade_no_diploma.population", + "records": 50, + "relative_error": -0.16401599932528943, + "share_error_pp": -0.5301630255091203, + "state": "MN", + "state_fips": "27", + "target": 130325.0, + "target_share": 0.03272483019246946 + }, + { + "calibrated_relative_error": 5.163647287531603e-12, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1082563.9899302102, + "estimate_share": 0.2724871379435281, + "households": 393, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.27.high_school_graduate_includes_equivalency.population", + "records": 544, + "relative_error": 0.18289346494658454, + "share_error_pp": 4.268312282720521, + "state": "MN", + "state_fips": "27", + "target": 915183.0, + "target_share": 0.22980401511632287 + }, + { + "calibrated_relative_error": 9.469203199330423e-11, + "category": "some_college_no_degree", + "estimate": 370690.4070687273, + "estimate_share": 0.09330475521524653, + "households": 204, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.27.some_college_no_degree.population", + "records": 230, + "relative_error": -0.5154152058346103, + "share_error_pp": -9.877926341650026, + "state": "MN", + "state_fips": "27", + "target": 764965.0, + "target_share": 0.1920840186317468 + }, + { + "calibrated_relative_error": 6.4432903457145585e-12, + "category": "associates_degree", + "estimate": 618739.6371183873, + "estimate_share": 0.15574007118182046, + "households": 304, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.27.associates_degree.population", + "records": 346, + "relative_error": 0.29702028755738374, + "share_error_pp": 3.595275432912927, + "state": "MN", + "state_fips": "27", + "target": 477047.0, + "target_share": 0.11978731685269119 + }, + { + "calibrated_relative_error": 5.539568803669681e-12, + "category": "bachelors_degree", + "estimate": 1089308.9657250142, + "estimate_share": 0.2741848843741507, + "households": 462, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.27.bachelors_degree.population", + "records": 571, + "relative_error": 0.05048310998014793, + "share_error_pp": 1.3802456471728786, + "state": "MN", + "state_fips": "27", + "target": 1036960.0, + "target_share": 0.2603824279024219 + }, + { + "calibrated_relative_error": 3.412381488487881e-12, + "category": "graduate_or_professional_degree", + "estimate": 531042.9180396189, + "estimate_share": 0.13366633862551058, + "households": 257, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.27.graduate_or_professional_degree.population", + "records": 313, + "relative_error": -0.04699852478030897, + "share_error_pp": -0.6255568743069068, + "state": "MN", + "state_fips": "27", + "target": 557232.0, + "target_share": 0.13992190736857965 + }, + { + "calibrated_relative_error": 3.617328658833685e-12, + "category": "less_than_9th_grade", + "estimate": 38321.42945203672, + "estimate_share": 0.019338742728372178, + "households": 31, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.28.less_than_9th_grade.population", + "records": 35, + "relative_error": -0.5246895533335394, + "share_error_pp": -2.1306507679723805, + "state": "MS", + "state_fips": "28", + "target": 80624.0, + "target_share": 0.04064525040809598 + }, + { + "calibrated_relative_error": 6.037392807911601e-13, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 123953.80210572049, + "estimate_share": 0.06255274720705085, + "households": 96, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.28.9th_to_12th_grade_no_diploma.population", + "records": 110, + "relative_error": -0.21235661704536046, + "share_error_pp": -1.6784236724201484, + "state": "MS", + "state_fips": "28", + "target": 157373.0, + "target_share": 0.07933698393125234 + }, + { + "calibrated_relative_error": 8.926193117986259e-14, + "category": "high_school_graduate_includes_equivalency", + "estimate": 796644.1321759778, + "estimate_share": 0.4020229970153096, + "households": 374, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.28.high_school_graduate_includes_equivalency.population", + "records": 527, + "relative_error": 0.36796993616604623, + "share_error_pp": 10.843839687879026, + "state": "MS", + "state_fips": "28", + "target": 582355.0, + "target_share": 0.2935846001365193 + }, + { + "calibrated_relative_error": 3.497202527569243e-13, + "category": "some_college_no_degree", + "estimate": 273972.76367230737, + "estimate_share": 0.13825916378905506, + "households": 201, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.28.some_college_no_degree.population", + "records": 243, + "relative_error": -0.30195710005093834, + "share_error_pp": -5.960663791915052, + "state": "MS", + "state_fips": "28", + "target": 392487.0, + "target_share": 0.19786580170820559 + }, + { + "calibrated_relative_error": 0.0, + "category": "associates_degree", + "estimate": 263735.38879297423, + "estimate_share": 0.13309291707445603, + "households": 190, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.28.associates_degree.population", + "records": 219, + "relative_error": 0.12302374679776462, + "share_error_pp": 1.4700215312711484, + "state": "MS", + "state_fips": "28", + "target": 234844.0, + "target_share": 0.11839270176174455 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 295067.62046496425, + "estimate_share": 0.14890459153635857, + "households": 225, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.28.bachelors_degree.population", + "records": 261, + "relative_error": -0.08693307526290539, + "share_error_pp": -1.4011658800150455, + "state": "MS", + "state_fips": "28", + "target": 323161.0, + "target_share": 0.16291625033650903 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "graduate_or_professional_degree", + "estimate": 189893.3249175849, + "estimate_share": 0.09582884064939763, + "households": 159, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.28.graduate_or_professional_degree.population", + "records": 193, + "relative_error": -0.10746799219025893, + "share_error_pp": -1.1429571068275566, + "state": "MS", + "state_fips": "28", + "target": 212758.0, + "target_share": 0.1072584117176732 + }, + { + "calibrated_relative_error": 3.0847102650000124e-11, + "category": "less_than_9th_grade", + "estimate": 54821.28549746805, + "estimate_share": 0.012747349732854612, + "households": 25, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.29.less_than_9th_grade.population", + "records": 32, + "relative_error": -0.5343157141616006, + "share_error_pp": -1.460901147745093, + "state": "MO", + "state_fips": "29", + "target": 117722.0, + "target_share": 0.027356361210305543 + }, + { + "calibrated_relative_error": 4.89608353859694e-13, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 135099.819482598, + "estimate_share": 0.03141416025112619, + "households": 65, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.29.9th_to_12th_grade_no_diploma.population", + "records": 80, + "relative_error": -0.40276549791300087, + "share_error_pp": -2.1152523232181997, + "state": "MO", + "state_fips": "29", + "target": 226209.0, + "target_share": 0.05256668348330819 + }, + { + "calibrated_relative_error": -2.1649348980190553e-14, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1222962.8909617765, + "estimate_share": 0.28437012266180284, + "households": 405, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.29.high_school_graduate_includes_equivalency.population", + "records": 561, + "relative_error": -0.03551746416063695, + "share_error_pp": -1.028880819484429, + "state": "MO", + "state_fips": "29", + "target": 1267999.0, + "target_share": 0.2946589308566471 + }, + { + "calibrated_relative_error": 4.640732242933154e-13, + "category": "some_college_no_degree", + "estimate": 822515.7154637692, + "estimate_share": 0.19125592168520103, + "households": 291, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.29.some_college_no_degree.population", + "records": 349, + "relative_error": -0.06231393076900282, + "share_error_pp": -1.2583152583083346, + "state": "MO", + "state_fips": "29", + "target": 877176.0, + "target_share": 0.20383907426828438 + }, + { + "calibrated_relative_error": 2.886579864025407e-15, + "category": "associates_degree", + "estimate": 503132.23165712715, + "estimate_share": 0.11699110045679684, + "households": 166, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.29.associates_degree.population", + "records": 189, + "relative_error": 0.346011133528076, + "share_error_pp": 3.012822827822223, + "state": "MO", + "state_fips": "29", + "target": 373795.0, + "target_share": 0.08686287217857461 + }, + { + "calibrated_relative_error": 1.8496315590255108e-13, + "category": "bachelors_degree", + "estimate": 887277.0936799098, + "estimate_share": 0.20631459697549398, + "households": 324, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.29.bachelors_degree.population", + "records": 392, + "relative_error": 0.024292620331122894, + "share_error_pp": 0.5018236085874289, + "state": "MO", + "state_fips": "29", + "target": 866234.0, + "target_share": 0.2012963608896197 + }, + { + "calibrated_relative_error": 1.0436096431476471e-14, + "category": "graduate_or_professional_degree", + "estimate": 674793.5705721426, + "estimate_share": 0.15690674823672443, + "households": 202, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.29.graduate_or_professional_degree.population", + "records": 242, + "relative_error": 0.17530779941572394, + "share_error_pp": 2.348703112346401, + "state": "MO", + "state_fips": "29", + "target": 574142.0, + "target_share": 0.13341971711326042 + }, + { + "calibrated_relative_error": -3.3306690738754696e-16, + "category": "less_than_9th_grade", + "estimate": 5342.867584237138, + "estimate_share": 0.006663795449416042, + "households": 9, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.30.less_than_9th_grade.population", + "records": 12, + "relative_error": -0.5498847865006624, + "share_error_pp": -0.8104496641771631, + "state": "MT", + "state_fips": "30", + "target": 11870.0, + "target_share": 0.014768292091187673 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 38814.22699019112, + "estimate_share": 0.048410346150618164, + "households": 36, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.30.9th_to_12th_grade_no_diploma.population", + "records": 38, + "relative_error": 0.2212644575606042, + "share_error_pp": 0.8868150763749874, + "state": "MT", + "state_fips": "30", + "target": 31782.0, + "target_share": 0.03954219538686829 + }, + { + "calibrated_relative_error": 0.0, + "category": "high_school_graduate_includes_equivalency", + "estimate": 238912.78707776847, + "estimate_share": 0.29797967444170803, + "households": 278, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.30.high_school_graduate_includes_equivalency.population", + "records": 381, + "relative_error": 0.1313336951660138, + "share_error_pp": 3.5238445525715587, + "state": "MT", + "state_fips": "30", + "target": 211178.0, + "target_share": 0.26274122891599244 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "some_college_no_degree", + "estimate": 106430.48570155399, + "estimate_share": 0.13274350807225171, + "households": 190, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.30.some_college_no_degree.population", + "records": 218, + "relative_error": -0.41622748703313506, + "share_error_pp": -9.408725625840376, + "state": "MT", + "state_fips": "30", + "target": 182315.0, + "target_share": 0.22683076433065547 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "associates_degree", + "estimate": 104361.64631558128, + "estimate_share": 0.13016318537690907, + "households": 126, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.30.associates_degree.population", + "records": 139, + "relative_error": 0.39970019200082185, + "share_error_pp": 3.7397906664276155, + "state": "MT", + "state_fips": "30", + "target": 74560.0, + "target_share": 0.09276527871263292 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 214645.5851594288, + "estimate_share": 0.2677128435379095, + "households": 285, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.30.bachelors_degree.population", + "records": 355, + "relative_error": 0.0993934908800902, + "share_error_pp": 2.480118828235084, + "state": "MT", + "state_fips": "30", + "target": 195240.0, + "target_share": 0.24291165525555863 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "graduate_or_professional_degree", + "estimate": 93267.84953157883, + "estimate_share": 0.11632664697118754, + "households": 147, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.30.graduate_or_professional_degree.population", + "records": 182, + "relative_error": -0.03652897058407889, + "share_error_pp": -0.41139383359170417, + "state": "MT", + "state_fips": "30", + "target": 96804.0, + "target_share": 0.12044058530710458 + }, + { + "calibrated_relative_error": 6.661338147750939e-15, + "category": "less_than_9th_grade", + "estimate": 63523.81795591994, + "estimate_share": 0.04805615150764454, + "households": 50, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.31.less_than_9th_grade.population", + "records": 65, + "relative_error": 0.2486499578550918, + "share_error_pp": 0.9712971225960771, + "state": "NE", + "state_fips": "31", + "target": 50874.0, + "target_share": 0.03834318028168377 + }, + { + "calibrated_relative_error": 1.3322676295501878e-15, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 43442.63312357677, + "estimate_share": 0.032864614036994706, + "households": 57, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.31.9th_to_12th_grade_no_diploma.population", + "records": 67, + "relative_error": -0.06903323496535285, + "share_error_pp": -0.23055350502500863, + "state": "NE", + "state_fips": "31", + "target": 46664.0, + "target_share": 0.03517014908724479 + }, + { + "calibrated_relative_error": -3.3306690738754696e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 328518.49266867235, + "estimate_share": 0.24852622157729534, + "households": 288, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.31.high_school_graduate_includes_equivalency.population", + "records": 384, + "relative_error": -0.016117122885078272, + "share_error_pp": -0.3130575530347318, + "state": "NE", + "state_fips": "31", + "target": 333900.0, + "target_share": 0.25165679710764266 + }, + { + "calibrated_relative_error": 2.220446049250313e-15, + "category": "some_college_no_degree", + "estimate": 240646.45629696266, + "estimate_share": 0.1820504959511312, + "households": 202, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.31.some_college_no_degree.population", + "records": 225, + "relative_error": -0.127789171969371, + "share_error_pp": -2.5895346963475063, + "state": "NE", + "state_fips": "31", + "target": 275904.0, + "target_share": 0.20794584291460627 + }, + { + "calibrated_relative_error": 0.0, + "category": "associates_degree", + "estimate": 168205.13226931164, + "estimate_share": 0.12724819730304213, + "households": 190, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.31.associates_degree.population", + "records": 212, + "relative_error": 0.11897294635687383, + "share_error_pp": 1.3952895122694875, + "state": "NE", + "state_fips": "31", + "target": 150321.0, + "target_share": 0.11329530218034725 + }, + { + "calibrated_relative_error": 0.0, + "category": "bachelors_degree", + "estimate": 281976.69967671233, + "estimate_share": 0.21331707440337894, + "households": 325, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.31.bachelors_degree.population", + "records": 419, + "relative_error": -0.048038528332605246, + "share_error_pp": -0.9930165021797444, + "state": "NE", + "state_fips": "31", + "target": 296206.0, + "target_share": 0.22324723942517638 + }, + { + "calibrated_relative_error": 6.661338147750939e-16, + "category": "graduate_or_professional_degree", + "estimate": 195553.29212729927, + "estimate_share": 0.14793724522051319, + "households": 201, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.31.graduate_or_professional_degree.population", + "records": 250, + "relative_error": 0.130771097892304, + "share_error_pp": 1.7595756217214293, + "state": "NE", + "state_fips": "31", + "target": 172938.0, + "target_share": 0.1303414890032989 + }, + { + "calibrated_relative_error": 1.9251267247000214e-13, + "category": "less_than_9th_grade", + "estimate": 103651.49936168498, + "estimate_share": 0.04471789482261304, + "households": 76, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.32.less_than_9th_grade.population", + "records": 107, + "relative_error": -0.17869227069336713, + "share_error_pp": -0.9734472785125223, + "state": "NV", + "state_fips": "32", + "target": 126203.0, + "target_share": 0.054452367607738264 + }, + { + "calibrated_relative_error": 4.6074255521944e-12, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 165304.8732641273, + "estimate_share": 0.07131672944253736, + "households": 110, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.32.9th_to_12th_grade_no_diploma.population", + "records": 156, + "relative_error": 0.04115281294523121, + "share_error_pp": 0.28123606284187475, + "state": "NV", + "state_fips": "32", + "target": 158771.0, + "target_share": 0.06850436881411862 + }, + { + "calibrated_relative_error": 4.766409489320722e-12, + "category": "high_school_graduate_includes_equivalency", + "estimate": 596628.9871646529, + "estimate_share": 0.2574009296580751, + "households": 390, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.32.high_school_graduate_includes_equivalency.population", + "records": 564, + "relative_error": -0.08181825753292138, + "share_error_pp": -2.296341791926204, + "state": "NV", + "state_fips": "32", + "target": 649794.0, + "target_share": 0.28036434757733714 + }, + { + "calibrated_relative_error": 7.66400276575041e-11, + "category": "some_college_no_degree", + "estimate": 351354.2998964777, + "estimate_share": 0.15158318717048336, + "households": 236, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.32.some_college_no_degree.population", + "records": 286, + "relative_error": -0.3153590742379062, + "share_error_pp": -6.9843266990299195, + "state": "NV", + "state_fips": "32", + "target": 513195.0, + "target_share": 0.22142645416078255 + }, + { + "calibrated_relative_error": 4.4859671533004075e-12, + "category": "associates_degree", + "estimate": 278984.87422215, + "estimate_share": 0.1203611750856898, + "households": 175, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.32.associates_degree.population", + "records": 198, + "relative_error": 0.33801844657779645, + "share_error_pp": 3.039781953614601, + "state": "NV", + "state_fips": "32", + "target": 208506.0, + "target_share": 0.0899633555495438 + }, + { + "calibrated_relative_error": 5.945910430682488e-12, + "category": "bachelors_degree", + "estimate": 532265.2099907506, + "estimate_share": 0.22963275808531924, + "households": 300, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.32.bachelors_degree.population", + "records": 370, + "relative_error": 0.24540858059242243, + "share_error_pp": 4.523173930660246, + "state": "NV", + "state_fips": "32", + "target": 427382.0, + "target_share": 0.18440101877871679 + }, + { + "calibrated_relative_error": 1.3459455772135698e-11, + "category": "graduate_or_professional_degree", + "estimate": 289707.8175316548, + "estimate_share": 0.12498732573528212, + "households": 182, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.32.graduate_or_professional_degree.population", + "records": 227, + "relative_error": 0.2389888957244053, + "share_error_pp": 2.4099238223519266, + "state": "NV", + "state_fips": "32", + "target": 233826.0, + "target_share": 0.10088808751176286 + }, + { + "calibrated_relative_error": 0.0, + "category": "less_than_9th_grade", + "estimate": 17732.496511168378, + "estimate_share": 0.01706884163306823, + "households": 18, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.33.less_than_9th_grade.population", + "records": 23, + "relative_error": 0.22852269025691951, + "share_error_pp": 0.3163722826862274, + "state": "NH", + "state_fips": "33", + "target": 14434.0, + "target_share": 0.013905118806205957 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 15468.448580350381, + "estimate_share": 0.014889527763954044, + "households": 41, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.33.9th_to_12th_grade_no_diploma.population", + "records": 42, + "relative_error": -0.5818094952458737, + "share_error_pp": -2.0744145474424234, + "state": "NH", + "state_fips": "33", + "target": 36989.0, + "target_share": 0.03563367323837828 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 274798.6668209626, + "estimate_share": 0.26451407572481966, + "households": 280, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.33.high_school_graduate_includes_equivalency.population", + "records": 391, + "relative_error": 0.006920474958640677, + "share_error_pp": 0.1603865568129359, + "state": "NH", + "state_fips": "33", + "target": 272910.0, + "target_share": 0.2629102101566903 + }, + { + "calibrated_relative_error": 0.0, + "category": "some_college_no_degree", + "estimate": 138087.00725356612, + "estimate_share": 0.13291897488382276, + "households": 167, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.33.some_college_no_degree.population", + "records": 182, + "relative_error": -0.2395629291776148, + "share_error_pp": -4.201635966655368, + "state": "NH", + "state_fips": "33", + "target": 181589.0, + "target_share": 0.17493533455037644 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "associates_degree", + "estimate": 92289.05791924518, + "estimate_share": 0.0888350556333968, + "households": 159, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.33.associates_degree.population", + "records": 185, + "relative_error": -0.08749374202332272, + "share_error_pp": -0.8597111875405892, + "state": "NH", + "state_fips": "33", + "target": 101138.0, + "target_share": 0.0974321675088027 + }, + { + "calibrated_relative_error": 0.0, + "category": "bachelors_degree", + "estimate": 266973.27261907153, + "estimate_share": 0.2569815540483437, + "households": 336, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.33.bachelors_degree.population", + "records": 436, + "relative_error": 0.03334225871392715, + "share_error_pp": 0.8089175660331765, + "state": "NH", + "state_fips": "33", + "target": 258359.0, + "target_share": 0.24889237838801195 + }, + { + "calibrated_relative_error": 0.0, + "category": "graduate_or_professional_degree", + "estimate": 233532.12332723622, + "estimate_share": 0.22479197031259487, + "households": 249, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.33.graduate_or_professional_degree.population", + "records": 342, + "relative_error": 0.35289963460650364, + "share_error_pp": 5.850085296106047, + "state": "NH", + "state_fips": "33", + "target": 172616.0, + "target_share": 0.1662911173515344 + }, + { + "calibrated_relative_error": -3.3306690738754696e-16, + "category": "less_than_9th_grade", + "estimate": 128205.85207005423, + "estimate_share": 0.01927271719145747, + "households": 64, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.34.less_than_9th_grade.population", + "records": 79, + "relative_error": -0.6262405301484935, + "share_error_pp": -3.2254005525894156, + "state": "NJ", + "state_fips": "34", + "target": 343017.0, + "target_share": 0.051526722717351627 + }, + { + "calibrated_relative_error": 4.440892098500626e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 84891.63932070251, + "estimate_share": 0.012761449888052822, + "households": 74, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.34.9th_to_12th_grade_no_diploma.population", + "records": 91, + "relative_error": -0.7157325569488218, + "share_error_pp": -3.209807539859731, + "state": "NJ", + "state_fips": "34", + "target": 298633.0, + "target_share": 0.04485952528665013 + }, + { + "calibrated_relative_error": 1.3322676295501878e-15, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1812351.0288548428, + "estimate_share": 0.27244410662065954, + "households": 581, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.34.high_school_graduate_includes_equivalency.population", + "records": 811, + "relative_error": 0.10310112775407965, + "share_error_pp": 2.5644839075027597, + "state": "NJ", + "state_fips": "34", + "target": 1642960.0, + "target_share": 0.24679926754563195 + }, + { + "calibrated_relative_error": 5.329070518200751e-15, + "category": "some_college_no_degree", + "estimate": 686561.0209245725, + "estimate_share": 0.10320820912080853, + "households": 299, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.34.some_college_no_degree.population", + "records": 349, + "relative_error": -0.28976764491272367, + "share_error_pp": -4.20014702125919, + "state": "NJ", + "state_fips": "34", + "target": 966671.0, + "target_share": 0.14520967933340043 + }, + { + "calibrated_relative_error": 7.593925488436071e-14, + "category": "associates_degree", + "estimate": 664207.101882409, + "estimate_share": 0.09984782616742396, + "households": 225, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.34.associates_degree.population", + "records": 249, + "relative_error": 0.5086803886875368, + "share_error_pp": 3.3714076634972, + "state": "NJ", + "state_fips": "34", + "target": 440257.0, + "target_share": 0.06613374953245196 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 2117527.9401849024, + "estimate_share": 0.31832023637964213, + "households": 692, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.34.bachelors_degree.population", + "records": 932, + "relative_error": 0.20554031130420514, + "share_error_pp": 5.44658680163832, + "state": "NJ", + "state_fips": "34", + "target": 1756497.0, + "target_share": 0.26385436836325893 + }, + { + "calibrated_relative_error": 4.440892098500626e-16, + "category": "graduate_or_professional_degree", + "estimate": 1158449.3340208884, + "estimate_share": 0.17414545463195555, + "households": 506, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.34.graduate_or_professional_degree.population", + "records": 715, + "relative_error": -0.04183970354796307, + "share_error_pp": -0.7471232589299437, + "state": "NJ", + "state_fips": "34", + "target": 1209035.0, + "target_share": 0.18161668722125499 + }, + { + "calibrated_relative_error": 1.5987211554602254e-14, + "category": "less_than_9th_grade", + "estimate": 63576.95724236408, + "estimate_share": 0.0430291742972073, + "households": 52, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.35.less_than_9th_grade.population", + "records": 68, + "relative_error": -0.15325559050711102, + "share_error_pp": -0.7514879082224493, + "state": "NM", + "state_fips": "35", + "target": 75084.0, + "target_share": 0.05054405337943179 + }, + { + "calibrated_relative_error": 7.793765632868599e-14, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 116157.36106279964, + "estimate_share": 0.07861583114179548, + "households": 101, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.35.9th_to_12th_grade_no_diploma.population", + "records": 127, + "relative_error": 0.10537628052605186, + "share_error_pp": 0.7876774813893248, + "state": "NM", + "state_fips": "35", + "target": 105084.0, + "target_share": 0.07073905632790223 + }, + { + "calibrated_relative_error": 7.327471962526033e-14, + "category": "high_school_graduate_includes_equivalency", + "estimate": 444410.8710785878, + "estimate_share": 0.3007793021348313, + "households": 331, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.35.high_school_graduate_includes_equivalency.population", + "records": 464, + "relative_error": 0.13579314727275182, + "share_error_pp": 3.7383956679110875, + "state": "NM", + "state_fips": "35", + "target": 391278.0, + "target_share": 0.2633953454557204 + }, + { + "calibrated_relative_error": 1.4122036873231991e-12, + "category": "some_college_no_degree", + "estimate": 237764.9438332721, + "estimate_share": 0.16092039716475018, + "households": 210, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.35.some_college_no_degree.population", + "records": 249, + "relative_error": -0.2410731753121791, + "share_error_pp": -4.997669179289146, + "state": "NM", + "state_fips": "35", + "target": 313291.0, + "target_share": 0.21089708895764164 + }, + { + "calibrated_relative_error": 1.325606291402437e-13, + "category": "associates_degree", + "estimate": 142732.43613266989, + "estimate_share": 0.0966019630163302, + "households": 159, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.35.associates_degree.population", + "records": 176, + "relative_error": 0.1095839122226272, + "share_error_pp": 1.0008483040348792, + "state": "NM", + "state_fips": "35", + "target": 128636.0, + "target_share": 0.08659347997598141 + }, + { + "calibrated_relative_error": 8.79296635503124e-14, + "category": "bachelors_degree", + "estimate": 307546.82953604625, + "estimate_share": 0.20814909531156345, + "households": 276, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.35.bachelors_degree.population", + "records": 332, + "relative_error": 0.1626424427879749, + "share_error_pp": 3.008032998019039, + "state": "NM", + "state_fips": "35", + "target": 264524.0, + "target_share": 0.17806876533137306 + }, + { + "calibrated_relative_error": 3.643751966819764e-13, + "category": "graduate_or_professional_degree", + "estimate": 165342.02672868085, + "estimate_share": 0.11190423693352214, + "households": 200, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.35.graduate_or_professional_degree.population", + "records": 239, + "relative_error": -0.2036276702581129, + "share_error_pp": -2.7857973638427262, + "state": "NM", + "state_fips": "35", + "target": 207619.0, + "target_share": 0.1397622105719494 + }, + { + "calibrated_relative_error": 1.0258460747536446e-13, + "category": "less_than_9th_grade", + "estimate": 553699.493470056, + "estimate_share": 0.03927611057303804, + "households": 141, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.36.less_than_9th_grade.population", + "records": 205, + "relative_error": -0.3679727356292073, + "share_error_pp": -2.2776926712233574, + "state": "NY", + "state_fips": "36", + "target": 876069.0, + "target_share": 0.06205303728527161 + }, + { + "calibrated_relative_error": 6.439293542825908e-15, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 914487.8416103341, + "estimate_share": 0.06486826520228485, + "households": 175, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.36.9th_to_12th_grade_no_diploma.population", + "records": 245, + "relative_error": 0.1263955007757811, + "share_error_pp": 0.7362450667321565, + "state": "NY", + "state_fips": "36", + "target": 811871.0, + "target_share": 0.057505814534963284 + }, + { + "calibrated_relative_error": 1.1324274851176597e-14, + "category": "high_school_graduate_includes_equivalency", + "estimate": 4208328.424141624, + "estimate_share": 0.29851349777906927, + "households": 765, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.36.high_school_graduate_includes_equivalency.population", + "records": 1145, + "relative_error": 0.239932499707314, + "share_error_pp": 5.811247406959288, + "state": "NY", + "state_fips": "36", + "target": 3393998.0, + "target_share": 0.24040102370947639 + }, + { + "calibrated_relative_error": 7.678302438307583e-13, + "category": "some_college_no_degree", + "estimate": 1155126.2003929194, + "estimate_share": 0.08193770250378446, + "households": 303, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.36.some_college_no_degree.population", + "records": 358, + "relative_error": -0.4193017097343963, + "share_error_pp": -5.895990473255977, + "state": "NY", + "state_fips": "36", + "target": 1989202.0, + "target_share": 0.14089760723634423 + }, + { + "calibrated_relative_error": -1.176836406102666e-14, + "category": "associates_degree", + "estimate": 1117772.1140064008, + "estimate_share": 0.07928802836722855, + "households": 323, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.36.associates_degree.population", + "records": 360, + "relative_error": -0.08966056147436574, + "share_error_pp": -0.7683007613048645, + "state": "NY", + "state_fips": "36", + "target": 1227863.0, + "target_share": 0.0869710359802772 + }, + { + "calibrated_relative_error": -1.4432899320127035e-14, + "category": "bachelors_degree", + "estimate": 3591213.226419458, + "estimate_share": 0.2547390587053792, + "households": 763, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.36.bachelors_degree.population", + "records": 1031, + "relative_error": 0.11356104932694433, + "share_error_pp": 2.63097155402946, + "state": "NY", + "state_fips": "36", + "target": 3224981.0, + "target_share": 0.22842934316508462 + }, + { + "calibrated_relative_error": 2.020605904817785e-14, + "category": "graduate_or_professional_degree", + "estimate": 2556987.901454118, + "estimate_share": 0.18137733686921567, + "households": 618, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.36.graduate_or_professional_degree.population", + "records": 819, + "relative_error": -0.01430026882162716, + "share_error_pp": -0.23648012193669965, + "state": "NY", + "state_fips": "36", + "target": 2594084.0, + "target_share": 0.18374213808858267 + }, + { + "calibrated_relative_error": 1.1848246828094489e-09, + "category": "less_than_9th_grade", + "estimate": 164024.18723387414, + "estimate_share": 0.021494403003303908, + "households": 65, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.37.less_than_9th_grade.population", + "records": 92, + "relative_error": -0.3896388339583373, + "share_error_pp": -1.3650081023416742, + "state": "NC", + "state_fips": "37", + "target": 268733.0, + "target_share": 0.03514448402672065 + }, + { + "calibrated_relative_error": 8.476064294882235e-11, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 300086.0889414683, + "estimate_share": 0.03932451329386094, + "households": 100, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.37.9th_to_12th_grade_no_diploma.population", + "records": 122, + "relative_error": -0.3033404783715188, + "share_error_pp": -1.7008302156827741, + "state": "NC", + "state_fips": "37", + "target": 430750.0, + "target_share": 0.05633281545068868 + }, + { + "calibrated_relative_error": 2.105338126057177e-11, + "category": "high_school_graduate_includes_equivalency", + "estimate": 2117152.2516923905, + "estimate_share": 0.2774403244098532, + "households": 466, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.37.high_school_graduate_includes_equivalency.population", + "records": 657, + "relative_error": 0.11942646959359893, + "share_error_pp": 3.0101273442877385, + "state": "NC", + "state_fips": "37", + "target": 1891283.0, + "target_share": 0.24733905096697584 + }, + { + "calibrated_relative_error": 3.725020292222325e-12, + "category": "some_college_no_degree", + "estimate": 1272524.6370951845, + "estimate_share": 0.1667568536240136, + "households": 282, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.37.some_college_no_degree.population", + "records": 328, + "relative_error": -0.11191928699827236, + "share_error_pp": -2.063466565534486, + "state": "NC", + "state_fips": "37", + "target": 1432893.0, + "target_share": 0.18739151927935846 + }, + { + "calibrated_relative_error": 2.3647750424515834e-13, + "category": "associates_degree", + "estimate": 874024.4323257237, + "estimate_share": 0.11453575048877443, + "households": 234, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.37.associates_degree.population", + "records": 263, + "relative_error": 0.116340691940378, + "share_error_pp": 1.214446661061809, + "state": "NC", + "state_fips": "37", + "target": 782937.0, + "target_share": 0.10239128387815634 + }, + { + "calibrated_relative_error": 2.148281552649678e-11, + "category": "bachelors_degree", + "estimate": 1815863.453181338, + "estimate_share": 0.23795820311548618, + "households": 470, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.37.bachelors_degree.population", + "records": 609, + "relative_error": 0.0502099728760208, + "share_error_pp": 1.1835993273623475, + "state": "NC", + "state_fips": "37", + "target": 1729048.0, + "target_share": 0.2261222098418627 + }, + { + "calibrated_relative_error": 2.091660178393795e-13, + "category": "graduate_or_professional_degree", + "estimate": 1087343.4620545118, + "estimate_share": 0.1424899520647077, + "households": 315, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.37.graduate_or_professional_degree.population", + "records": 397, + "relative_error": -0.021183766635959556, + "share_error_pp": -0.2788684491529664, + "state": "NC", + "state_fips": "37", + "target": 1110876.0, + "target_share": 0.14527863655623735 + }, + { + "calibrated_relative_error": 3.774758283725532e-15, + "category": "less_than_9th_grade", + "estimate": 3208.8368928766304, + "estimate_share": 0.006162704017335715, + "households": 14, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.38.less_than_9th_grade.population", + "records": 14, + "relative_error": -0.753412979875768, + "share_error_pp": -1.8333922590296585, + "state": "ND", + "state_fips": "38", + "target": 13013.0, + "target_share": 0.0244966266076323 + }, + { + "calibrated_relative_error": 1.709743457922741e-14, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 21221.14331944586, + "estimate_share": 0.04075608376278851, + "households": 38, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.38.9th_to_12th_grade_no_diploma.population", + "records": 41, + "relative_error": 0.17315182262401785, + "share_error_pp": 0.6704022077899503, + "state": "ND", + "state_fips": "38", + "target": 18089.0, + "target_share": 0.03405206168488901 + }, + { + "calibrated_relative_error": 1.5543122344752192e-15, + "category": "high_school_graduate_includes_equivalency", + "estimate": 149232.48370194252, + "estimate_share": 0.2866071593942829, + "households": 241, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.38.high_school_graduate_includes_equivalency.population", + "records": 312, + "relative_error": 0.1544783056531016, + "share_error_pp": 4.327111529922551, + "state": "ND", + "state_fips": "38", + "target": 129264.0, + "target_share": 0.24333604409505738 + }, + { + "calibrated_relative_error": 1.9984014443252818e-15, + "category": "some_college_no_degree", + "estimate": 69738.51750258291, + "estimate_share": 0.13393570827182844, + "households": 156, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.38.some_college_no_degree.population", + "records": 178, + "relative_error": -0.39501429213620787, + "share_error_pp": -8.306265021134978, + "state": "ND", + "state_fips": "38", + "target": 115273.0, + "target_share": 0.21699835848317822 + }, + { + "calibrated_relative_error": 0.0, + "category": "associates_degree", + "estimate": 87702.71434201782, + "estimate_share": 0.1684366915646715, + "households": 168, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.38.associates_degree.population", + "records": 195, + "relative_error": 0.16594940630175237, + "share_error_pp": 2.683704095173817, + "state": "ND", + "state_fips": "38", + "target": 75220.0, + "target_share": 0.14159965061293334 + }, + { + "calibrated_relative_error": 0.0, + "category": "bachelors_degree", + "estimate": 130079.0216586855, + "estimate_share": 0.2498221430720446, + "households": 252, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.38.bachelors_degree.population", + "records": 313, + "relative_error": 0.04337834507371796, + "share_error_pp": 1.5132299392637356, + "state": "ND", + "state_fips": "38", + "target": 124671.0, + "target_share": 0.23468984367940723 + }, + { + "calibrated_relative_error": 0.0, + "category": "graduate_or_professional_degree", + "estimate": 59503.80003487826, + "estimate_share": 0.1142795099170483, + "households": 116, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.38.graduate_or_professional_degree.population", + "records": 137, + "relative_error": 0.06855942310236429, + "share_error_pp": 0.94520950801458, + "state": "ND", + "state_fips": "38", + "target": 55686.0, + "target_share": 0.1048274148369025 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "less_than_9th_grade", + "estimate": 215563.3504155018, + "estimate_share": 0.026125771121427797, + "households": 39, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.39.less_than_9th_grade.population", + "records": 63, + "relative_error": 0.006552812922589579, + "share_error_pp": 0.017739404604834308, + "state": "OH", + "state_fips": "39", + "target": 214160.0, + "target_share": 0.025948377075379454 + }, + { + "calibrated_relative_error": 1.3322676295501878e-13, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 395974.8445349334, + "estimate_share": 0.04799121992779471, + "households": 109, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.39.9th_to_12th_grade_no_diploma.population", + "records": 126, + "relative_error": -0.0822124615305928, + "share_error_pp": -0.4284170188413212, + "state": "OH", + "state_fips": "39", + "target": 431445.0, + "target_share": 0.05227539011620792 + }, + { + "calibrated_relative_error": 4.2099657093785936e-13, + "category": "high_school_graduate_includes_equivalency", + "estimate": 2735493.5042251293, + "estimate_share": 0.3315353795428799, + "households": 599, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.39.high_school_graduate_includes_equivalency.population", + "records": 814, + "relative_error": 0.05944957454415256, + "share_error_pp": 1.8691805267831485, + "state": "OH", + "state_fips": "39", + "target": 2581995.0, + "target_share": 0.31284357427504844 + }, + { + "calibrated_relative_error": 5.064837438339964e-13, + "category": "some_college_no_degree", + "estimate": 1313675.083824303, + "estimate_share": 0.15921433073740213, + "households": 327, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.39.some_college_no_degree.population", + "records": 374, + "relative_error": -0.17945616854647062, + "share_error_pp": -3.4766144974766684, + "state": "OH", + "state_fips": "39", + "target": 1600981.0, + "target_share": 0.1939804757121688 + }, + { + "calibrated_relative_error": 8.093747894122316e-12, + "category": "associates_degree", + "estimate": 1071393.1071639284, + "estimate_share": 0.12985032495035503, + "households": 263, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.39.associates_degree.population", + "records": 286, + "relative_error": 0.41965414379480803, + "share_error_pp": 3.840992103968162, + "state": "OH", + "state_fips": "39", + "target": 754686.0, + "target_share": 0.09144040391067342 + }, + { + "calibrated_relative_error": 2.2315482794965646e-13, + "category": "bachelors_degree", + "estimate": 1548340.1248457672, + "estimate_share": 0.1876551818380647, + "households": 492, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.39.bachelors_degree.population", + "records": 624, + "relative_error": -0.05492203913413307, + "share_error_pp": -1.084941813455234, + "state": "OH", + "state_fips": "39", + "target": 1638320.0, + "target_share": 0.19850459997261705 + }, + { + "calibrated_relative_error": 3.206324095117452e-13, + "category": "graduate_or_professional_degree", + "estimate": 970545.1679196926, + "estimate_share": 0.11762779188207567, + "households": 358, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.39.graduate_or_professional_degree.population", + "records": 436, + "relative_error": -0.05929676093322278, + "share_error_pp": -0.7379387055829245, + "state": "OH", + "state_fips": "39", + "target": 1031723.0, + "target_share": 0.12500717893790492 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "less_than_9th_grade", + "estimate": 44883.707663047084, + "estimate_share": 0.016468134969965437, + "households": 47, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.40.less_than_9th_grade.population", + "records": 58, + "relative_error": -0.5493015387244612, + "share_error_pp": -2.004748299454379, + "state": "OK", + "state_fips": "40", + "target": 99587.0, + "target_share": 0.03651561796450922 + }, + { + "calibrated_relative_error": 0.0, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 174601.01396990888, + "estimate_share": 0.06406228927287502, + "households": 82, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.40.9th_to_12th_grade_no_diploma.population", + "records": 96, + "relative_error": 0.04545871162577386, + "share_error_pp": 0.28250109068762363, + "state": "OK", + "state_fips": "40", + "target": 167009.0, + "target_share": 0.061237278365998786 + }, + { + "calibrated_relative_error": 0.0, + "category": "high_school_graduate_includes_equivalency", + "estimate": 942044.1262889998, + "estimate_share": 0.34564234166784097, + "households": 362, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.40.high_school_graduate_includes_equivalency.population", + "records": 492, + "relative_error": 0.12179093069633495, + "share_error_pp": 3.7724164929712645, + "state": "OK", + "state_fips": "40", + "target": 839768.0, + "target_share": 0.3079181767381283 + }, + { + "calibrated_relative_error": 0.0, + "category": "some_college_no_degree", + "estimate": 627863.0581627841, + "estimate_share": 0.2303671894065188, + "households": 240, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.40.some_college_no_degree.population", + "records": 301, + "relative_error": 0.052432030686063946, + "share_error_pp": 1.1617785246128305, + "state": "OK", + "state_fips": "40", + "target": 596583.0, + "target_share": 0.2187494041603905 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "associates_degree", + "estimate": 210773.98550919344, + "estimate_share": 0.07733439642689474, + "households": 124, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.40.associates_degree.population", + "records": 139, + "relative_error": -0.061921760007506266, + "share_error_pp": -0.5051704706703866, + "state": "OK", + "state_fips": "40", + "target": 224687.0, + "target_share": 0.08238610113359861 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 497192.2215214299, + "estimate_share": 0.1824231783947058, + "households": 286, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.40.bachelors_degree.population", + "records": 333, + "relative_error": -0.03180522560453747, + "share_error_pp": -0.5871304973852354, + "state": "OK", + "state_fips": "40", + "target": 513525.0, + "target_share": 0.18829448336855814 + }, + { + "calibrated_relative_error": 0.0, + "category": "graduate_or_professional_degree", + "estimate": 228130.09456000137, + "estimate_share": 0.08370246986119934, + "households": 174, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.40.graduate_or_professional_degree.population", + "records": 206, + "relative_error": -0.20257932236922116, + "share_error_pp": -2.1196468407617104, + "state": "OK", + "state_fips": "40", + "target": 286085.0, + "target_share": 0.10489893826881644 + }, + { + "calibrated_relative_error": 0.0, + "category": "less_than_9th_grade", + "estimate": 28671.932462484365, + "estimate_share": 0.009311430431140431, + "households": 46, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.41.less_than_9th_grade.population", + "records": 64, + "relative_error": -0.698919117268882, + "share_error_pp": -2.1557759472238973, + "state": "OR", + "state_fips": "41", + "target": 95230.0, + "target_share": 0.030869189903379404 + }, + { + "calibrated_relative_error": 4.440892098500626e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 183396.02625347744, + "estimate_share": 0.05955926905315026, + "households": 88, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.41.9th_to_12th_grade_no_diploma.population", + "records": 121, + "relative_error": 0.2890702625534367, + "share_error_pp": 1.344187277515186, + "state": "OR", + "state_fips": "41", + "target": 142270.0, + "target_share": 0.0461173962779984 + }, + { + "calibrated_relative_error": -4.440892098500626e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 715137.9131102115, + "estimate_share": 0.2322465336199282, + "households": 329, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.41.high_school_graduate_includes_equivalency.population", + "records": 460, + "relative_error": 0.02249471066150721, + "share_error_pp": 0.5531572322300643, + "state": "OR", + "state_fips": "41", + "target": 699405.0, + "target_share": 0.22671496129762755 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "some_college_no_degree", + "estimate": 649554.3773696739, + "estimate_share": 0.21094777633263115, + "households": 314, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.41.some_college_no_degree.population", + "records": 413, + "relative_error": -0.07100612216544877, + "share_error_pp": -1.5701381693439265, + "state": "OR", + "state_fips": "41", + "target": 699202.0, + "target_share": 0.2266491580260704 + }, + { + "calibrated_relative_error": 0.0, + "category": "associates_degree", + "estimate": 335357.05275459983, + "estimate_share": 0.10890978033666086, + "households": 203, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.41.associates_degree.population", + "records": 233, + "relative_error": 0.19174079962260193, + "share_error_pp": 1.7692507334446563, + "state": "OR", + "state_fips": "41", + "target": 281401.0, + "target_share": 0.0912172730022143 + }, + { + "calibrated_relative_error": 0.0, + "category": "bachelors_degree", + "estimate": 807622.1042928004, + "estimate_share": 0.2622814855124715, + "households": 455, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.41.bachelors_degree.population", + "records": 595, + "relative_error": 0.14183489413687567, + "share_error_pp": 3.3006679705057245, + "state": "OR", + "state_fips": "41", + "target": 707302.0, + "target_share": 0.22927480580741424 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "graduate_or_professional_degree", + "estimate": 359479.48225278413, + "estimate_share": 0.11674372471401766, + "households": 281, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.41.graduate_or_professional_degree.population", + "records": 354, + "relative_error": -0.21876572662675708, + "share_error_pp": -3.241349097127803, + "state": "OR", + "state_fips": "41", + "target": 460143.0, + "target_share": 0.1491572156852957 + }, + { + "calibrated_relative_error": 5.3514970232981796e-12, + "category": "less_than_9th_grade", + "estimate": 189829.077151899, + "estimate_share": 0.020487125366576778, + "households": 74, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.42.less_than_9th_grade.population", + "records": 114, + "relative_error": -0.28917077452079176, + "share_error_pp": -0.8335623464957469, + "state": "PA", + "state_fips": "42", + "target": 267053.0, + "target_share": 0.028822748831534246 + }, + { + "calibrated_relative_error": 2.6258994978434202e-12, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 471026.52977867157, + "estimate_share": 0.050835097084928955, + "households": 137, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.42.9th_to_12th_grade_no_diploma.population", + "records": 177, + "relative_error": 0.0669115889941505, + "share_error_pp": 0.31859784057202273, + "state": "PA", + "state_fips": "42", + "target": 441486.0, + "target_share": 0.04764911867920873 + }, + { + "calibrated_relative_error": 6.0960125836118095e-12, + "category": "high_school_graduate_includes_equivalency", + "estimate": 3051101.123891441, + "estimate_share": 0.3292872312772656, + "households": 818, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.42.high_school_graduate_includes_equivalency.population", + "records": 1137, + "relative_error": 0.016123599926146426, + "share_error_pp": 0.5210388026251511, + "state": "PA", + "state_fips": "42", + "target": 3002687.0, + "target_share": 0.3240768432510141 + }, + { + "calibrated_relative_error": 6.534395247115299e-11, + "category": "some_college_no_degree", + "estimate": 966131.2686131552, + "estimate_share": 0.10426881233168114, + "households": 358, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.42.some_college_no_degree.population", + "records": 403, + "relative_error": -0.2900922030140124, + "share_error_pp": -4.261438858182945, + "state": "PA", + "state_fips": "42", + "target": 1360925.0, + "target_share": 0.1468832009135106 + }, + { + "calibrated_relative_error": 3.2529534621517087e-12, + "category": "associates_degree", + "estimate": 808562.8197941338, + "estimate_share": 0.08726338506413339, + "households": 341, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.42.associates_degree.population", + "records": 378, + "relative_error": -0.01836990460761667, + "share_error_pp": -0.1637040229878553, + "state": "PA", + "state_fips": "42", + "target": 823694.0, + "target_share": 0.08890042529401194 + }, + { + "calibrated_relative_error": 5.023093052614058e-12, + "category": "bachelors_degree", + "estimate": 2146775.7491599964, + "estimate_share": 0.2316887621582564, + "households": 696, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.42.bachelors_degree.population", + "records": 886, + "relative_error": 0.08719415313060375, + "share_error_pp": 1.8572049414923852, + "state": "PA", + "state_fips": "42", + "target": 1974602.0, + "target_share": 0.21311671274333255 + }, + { + "calibrated_relative_error": 1.3584688929313415e-12, + "category": "graduate_or_professional_degree", + "estimate": 1632347.6071126992, + "estimate_share": 0.17616958671715768, + "households": 517, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.42.graduate_or_professional_degree.population", + "records": 651, + "relative_error": 0.17021882956632206, + "share_error_pp": 2.5618636429769888, + "state": "PA", + "state_fips": "42", + "target": 1394908.0, + "target_share": 0.1505509502873878 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "less_than_9th_grade", + "estimate": 23985.61001434172, + "estimate_share": 0.03013288976617974, + "households": 45, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.44.less_than_9th_grade.population", + "records": 61, + "relative_error": -0.37920620093843416, + "share_error_pp": -1.834089547225603, + "state": "RI", + "state_fips": "44", + "target": 38637.0, + "target_share": 0.04847378523843577 + }, + { + "calibrated_relative_error": 0.0, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 28861.005623699002, + "estimate_share": 0.03625780209383944, + "households": 60, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.44.9th_to_12th_grade_no_diploma.population", + "records": 70, + "relative_error": -0.23514587311975932, + "share_error_pp": -1.1083083901117083, + "state": "RI", + "state_fips": "44", + "target": 37734.0, + "target_share": 0.047340885994956526 + }, + { + "calibrated_relative_error": 0.0, + "category": "high_school_graduate_includes_equivalency", + "estimate": 221306.05596626166, + "estimate_share": 0.2780246566600564, + "households": 287, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.44.high_school_graduate_includes_equivalency.population", + "records": 397, + "relative_error": 0.011485998026727007, + "share_error_pp": 0.35280628853565643, + "state": "RI", + "state_fips": "44", + "target": 218793.0, + "target_share": 0.2744965937746998 + }, + { + "calibrated_relative_error": 0.0, + "category": "some_college_no_degree", + "estimate": 119587.18829350811, + "estimate_share": 0.15023622747726717, + "households": 147, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.44.some_college_no_degree.population", + "records": 167, + "relative_error": -0.060181631549309555, + "share_error_pp": -0.9404707446892563, + "state": "RI", + "state_fips": "44", + "target": 127245.0, + "target_share": 0.15964093492415973 + }, + { + "calibrated_relative_error": 6.661338147750939e-16, + "category": "associates_degree", + "estimate": 116899.08344917544, + "estimate_share": 0.14685918737256365, + "households": 130, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.44.associates_degree.population", + "records": 151, + "relative_error": 0.8328773334353852, + "share_error_pp": 6.684237580017979, + "state": "RI", + "state_fips": "44", + "target": 63779.0, + "target_share": 0.08001681157238386 + }, + { + "calibrated_relative_error": 0.0, + "category": "bachelors_degree", + "estimate": 188998.21410790048, + "estimate_share": 0.2374366275576461, + "households": 312, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.44.bachelors_degree.population", + "records": 404, + "relative_error": 0.05159668442287102, + "share_error_pp": 1.1954549446564267, + "state": "RI", + "state_fips": "44", + "target": 179725.0, + "target_share": 0.22548207811108184 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "graduate_or_professional_degree", + "estimate": 96357.19291978156, + "estimate_share": 0.12105260907244761, + "households": 209, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.44.graduate_or_professional_degree.population", + "records": 275, + "relative_error": -0.2653293921042601, + "share_error_pp": -4.349630131183482, + "state": "RI", + "state_fips": "44", + "target": 131157.0, + "target_share": 0.16454891038428243 + }, + { + "calibrated_relative_error": 0.0, + "category": "less_than_9th_grade", + "estimate": 94332.18471003907, + "estimate_share": 0.024669577363408017, + "households": 56, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.45.less_than_9th_grade.population", + "records": 75, + "relative_error": -0.13287263450560205, + "share_error_pp": -0.37649563224720284, + "state": "SC", + "state_fips": "45", + "target": 108787.0, + "target_share": 0.028434533685880045 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 201843.74671087216, + "estimate_share": 0.052785800944924716, + "households": 81, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.45.9th_to_12th_grade_no_diploma.population", + "records": 93, + "relative_error": -0.14940455753392512, + "share_error_pp": -0.9238425663569652, + "state": "SC", + "state_fips": "45", + "target": 237297.0, + "target_share": 0.06202422660849437 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1337032.0378291686, + "estimate_share": 0.34965812989457357, + "households": 393, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.45.high_school_graduate_includes_equivalency.population", + "records": 533, + "relative_error": 0.2629618511810994, + "share_error_pp": 7.295078234854752, + "state": "SC", + "state_fips": "45", + "target": 1058648.0, + "target_share": 0.27670734754602605 + }, + { + "calibrated_relative_error": 6.661338147750939e-16, + "category": "some_college_no_degree", + "estimate": 534769.8767219065, + "estimate_share": 0.13985202278483067, + "households": 167, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.45.some_college_no_degree.population", + "records": 192, + "relative_error": -0.2855474504151534, + "share_error_pp": -5.579023012665941, + "state": "SC", + "state_fips": "45", + "target": 748503.0, + "target_share": 0.19564225291149007 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "associates_degree", + "estimate": 510478.6542042575, + "estimate_share": 0.13349942748564508, + "households": 172, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.45.associates_degree.population", + "records": 197, + "relative_error": 0.28470135850393974, + "share_error_pp": 2.964033743672556, + "state": "SC", + "state_fips": "45", + "target": 397352.0, + "target_share": 0.10385909004891952 + }, + { + "calibrated_relative_error": 0.0, + "category": "bachelors_degree", + "estimate": 804271.9893951595, + "estimate_share": 0.2103317136626692, + "households": 313, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.45.bachelors_degree.population", + "records": 384, + "relative_error": 0.03491927322171762, + "share_error_pp": 0.7205684486605995, + "state": "SC", + "state_fips": "45", + "target": 777135.0, + "target_share": 0.2031260291760632 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "graduate_or_professional_degree", + "estimate": 341098.0527495231, + "estimate_share": 0.08920332786394874, + "households": 202, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.45.graduate_or_professional_degree.population", + "records": 264, + "relative_error": -0.31527589309827264, + "share_error_pp": -4.1003192159178, + "state": "SC", + "state_fips": "45", + "target": 498154.0, + "target_share": 0.13020652002312674 + }, + { + "calibrated_relative_error": 3.885780586188048e-14, + "category": "less_than_9th_grade", + "estimate": 6321.1024789058265, + "estimate_share": 0.010230300105620153, + "households": 13, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.46.less_than_9th_grade.population", + "records": 20, + "relative_error": -0.48251310037610917, + "share_error_pp": -0.9367130328716021, + "state": "SD", + "state_fips": "46", + "target": 12215.0, + "target_share": 0.019597430434336174 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 30039.638213052047, + "estimate_share": 0.048617233308480265, + "households": 42, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.46.9th_to_12th_grade_no_diploma.population", + "records": 43, + "relative_error": 0.2005290629466887, + "share_error_pp": 0.8472582933698458, + "state": "SD", + "state_fips": "46", + "target": 25022.0, + "target_share": 0.04014465037478181 + }, + { + "calibrated_relative_error": 8.881784197001252e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 132609.81808847073, + "estimate_share": 0.21462050971709343, + "households": 264, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.46.high_school_graduate_includes_equivalency.population", + "records": 329, + "relative_error": -0.23622854952644645, + "share_error_pp": -6.3938954806985, + "state": "SD", + "state_fips": "46", + "target": 173625.0, + "target_share": 0.2785594645240784 + }, + { + "calibrated_relative_error": 1.9984014443252818e-15, + "category": "some_college_no_degree", + "estimate": 86263.29716898665, + "estimate_share": 0.13961162963011892, + "households": 155, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.46.some_college_no_degree.population", + "records": 181, + "relative_error": -0.26176671856478206, + "share_error_pp": -4.786109600906374, + "state": "SD", + "state_fips": "46", + "target": 116851.0, + "target_share": 0.18747272563918266 + }, + { + "calibrated_relative_error": 0.0, + "category": "associates_degree", + "estimate": 122894.33929936688, + "estimate_share": 0.1988966286355888, + "households": 214, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.46.associates_degree.population", + "records": 250, + "relative_error": 0.4890868690096557, + "share_error_pp": 6.6487628738268745, + "state": "SD", + "state_fips": "46", + "target": 82530.0, + "target_share": 0.13240899989732005 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 168651.65616698706, + "estimate_share": 0.27295191964627, + "households": 350, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.46.bachelors_degree.population", + "records": 449, + "relative_error": 0.17796535752093323, + "share_error_pp": 4.325046159102822, + "state": "SD", + "state_fips": "46", + "target": 143172.0, + "target_share": 0.2297014580552418 + }, + { + "calibrated_relative_error": 0.0, + "category": "graduate_or_professional_degree", + "estimate": 71100.60308167453, + "estimate_share": 0.11507177895682844, + "households": 154, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.46.graduate_or_professional_degree.population", + "records": 184, + "relative_error": 0.01745257053669147, + "share_error_pp": 0.29565078817693907, + "state": "SD", + "state_fips": "46", + "target": 69881.0, + "target_share": 0.11211527107505904 + }, + { + "calibrated_relative_error": 1.2976508756423755e-11, + "category": "less_than_9th_grade", + "estimate": 52824.826310603574, + "estimate_share": 0.01057010892586286, + "households": 34, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.47.less_than_9th_grade.population", + "records": 46, + "relative_error": -0.6935968265598419, + "share_error_pp": -2.3934243870602225, + "state": "TN", + "state_fips": "47", + "target": 172403.0, + "target_share": 0.03450435279646508 + }, + { + "calibrated_relative_error": 4.440892098500626e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 281661.28719018516, + "estimate_share": 0.05635968338624494, + "households": 85, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.47.9th_to_12th_grade_no_diploma.population", + "records": 97, + "relative_error": -0.057500419313740725, + "share_error_pp": -0.3450489937070832, + "state": "TN", + "state_fips": "47", + "target": 298845.0, + "target_share": 0.05981017332331577 + }, + { + "calibrated_relative_error": 1.3513634655737405e-12, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1493947.4958707779, + "estimate_share": 0.29893496796418995, + "households": 416, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.47.high_school_graduate_includes_equivalency.population", + "records": 575, + "relative_error": -0.025344226807382686, + "share_error_pp": -0.7835212628129806, + "state": "TN", + "state_fips": "47", + "target": 1532795.0, + "target_share": 0.30677018059231975 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "some_college_no_degree", + "estimate": 719842.4612557725, + "estimate_share": 0.14403858481608312, + "households": 251, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.47.some_college_no_degree.population", + "records": 292, + "relative_error": -0.26182193375681295, + "share_error_pp": -5.112796783876447, + "state": "TN", + "state_fips": "47", + "target": 975161.0, + "target_share": 0.19516655265484759 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "associates_degree", + "estimate": 576771.7078558122, + "estimate_share": 0.11541050303781354, + "households": 200, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.47.associates_degree.population", + "records": 223, + "relative_error": 0.4506330680478172, + "share_error_pp": 3.5835723759758533, + "state": "TN", + "state_fips": "47", + "target": 397600.0, + "target_share": 0.07957477927805501 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 1092841.4549406029, + "estimate_share": 0.21867470324463498, + "households": 368, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.47.bachelors_degree.population", + "records": 450, + "relative_error": 0.09282396975708673, + "share_error_pp": 1.8533726196034717, + "state": "TN", + "state_fips": "47", + "target": 1000016.0, + "target_share": 0.20014097704860026 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "graduate_or_professional_degree", + "estimate": 779677.6489148187, + "estimate_share": 0.1560114486251707, + "households": 237, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.47.graduate_or_professional_degree.population", + "records": 284, + "relative_error": 0.2580762336903961, + "share_error_pp": 3.197846431877417, + "state": "TN", + "state_fips": "47", + "target": 619738.0, + "target_share": 0.12403298430639652 + }, + { + "calibrated_relative_error": -3.3306690738754696e-16, + "category": "less_than_9th_grade", + "estimate": 1172657.7427943682, + "estimate_share": 0.05705196390057366, + "households": 167, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.48.less_than_9th_grade.population", + "records": 234, + "relative_error": -0.17837094606398518, + "share_error_pp": -1.2308868280702496, + "state": "TX", + "state_fips": "48", + "target": 1427235.0, + "target_share": 0.06936083218127616 + }, + { + "calibrated_relative_error": 0.0, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 1328064.6387685607, + "estimate_share": 0.06461279626918284, + "households": 191, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.48.9th_to_12th_grade_no_diploma.population", + "records": 232, + "relative_error": 0.012182670849765875, + "share_error_pp": 0.08482720749129341, + "state": "TX", + "state_fips": "48", + "target": 1312080.0, + "target_share": 0.06376452419426991 + }, + { + "calibrated_relative_error": 0.0, + "category": "high_school_graduate_includes_equivalency", + "estimate": 5493861.046576352, + "estimate_share": 0.26728648152456236, + "households": 639, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.48.high_school_graduate_includes_equivalency.population", + "records": 853, + "relative_error": 0.09623464535819526, + "share_error_pp": 2.3733777745544278, + "state": "TX", + "state_fips": "48", + "target": 5011574.0, + "target_share": 0.24355270377901808 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "some_college_no_degree", + "estimate": 2943121.192922188, + "estimate_share": 0.14318827900584974, + "households": 406, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.48.some_college_no_degree.population", + "records": 505, + "relative_error": -0.26792837661352886, + "share_error_pp": -5.21886957939737, + "state": "TX", + "state_fips": "48", + "target": 4020264.0, + "target_share": 0.19537697479982344 + }, + { + "calibrated_relative_error": 2.4424906541753444e-15, + "category": "associates_degree", + "estimate": 2706538.087840119, + "estimate_share": 0.13167807421373018, + "households": 322, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.48.associates_degree.population", + "records": 390, + "relative_error": 0.723735040744357, + "share_error_pp": 5.537141490610363, + "state": "TX", + "state_fips": "48", + "target": 1570159.0, + "target_share": 0.07630665930762655 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 4613787.383899184, + "estimate_share": 0.2244692732287672, + "households": 665, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.48.bachelors_degree.population", + "records": 870, + "relative_error": 0.014755627908249913, + "share_error_pp": 0.3508634681545525, + "state": "TX", + "state_fips": "48", + "target": 4546698.0, + "target_share": 0.22096063854722167 + }, + { + "calibrated_relative_error": 0.0, + "category": "graduate_or_professional_degree", + "estimate": 2296174.5764372144, + "estimate_share": 0.11171313185733406, + "households": 391, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.48.graduate_or_professional_degree.population", + "records": 479, + "relative_error": -0.14606986728375493, + "share_error_pp": -1.8964535333430148, + "state": "TX", + "state_fips": "48", + "target": 2688949.0, + "target_share": 0.1306776671907642 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "less_than_9th_grade", + "estimate": 24702.183913103072, + "estimate_share": 0.011480966425331059, + "households": 23, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.49.less_than_9th_grade.population", + "records": 35, + "relative_error": -0.5534028074721025, + "share_error_pp": -1.4207263765584432, + "state": "UT", + "state_fips": "49", + "target": 55312.0, + "target_share": 0.02568823019091549 + }, + { + "calibrated_relative_error": 0.0, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 72975.0411349302, + "estimate_share": 0.03391700102730065, + "households": 33, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.49.9th_to_12th_grade_no_diploma.population", + "records": 40, + "relative_error": -0.11107948041354787, + "share_error_pp": -0.42094375265939177, + "state": "UT", + "state_fips": "49", + "target": 82094.0, + "target_share": 0.03812643855389457 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 555356.8565561445, + "estimate_share": 0.2581161830317512, + "households": 296, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.49.high_school_graduate_includes_equivalency.population", + "records": 426, + "relative_error": 0.15336755191729456, + "share_error_pp": 3.4491761007642037, + "state": "UT", + "state_fips": "49", + "target": 481509.0, + "target_share": 0.22362442202410918 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "some_college_no_degree", + "estimate": 471764.75002357067, + "estimate_share": 0.21926463161025508, + "households": 222, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.49.some_college_no_degree.population", + "records": 294, + "relative_error": -0.012990769323078966, + "share_error_pp": -0.27180509409569786, + "state": "UT", + "state_fips": "49", + "target": 477974.0, + "target_share": 0.22198268255121206 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "associates_degree", + "estimate": 239484.9841287345, + "estimate_share": 0.11130671975502872, + "households": 185, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.49.associates_degree.population", + "records": 221, + "relative_error": 0.11891093998492996, + "share_error_pp": 1.1904155018942402, + "state": "UT", + "state_fips": "49", + "target": 214034.0, + "target_share": 0.09940256473608632 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 577786.2543060731, + "estimate_share": 0.2685408144494912, + "households": 342, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.49.bachelors_degree.population", + "records": 465, + "relative_error": 0.054302533097955186, + "share_error_pp": 1.4023824884173641, + "state": "UT", + "state_fips": "49", + "target": 548027.0, + "target_share": 0.25451698956531754 + }, + { + "calibrated_relative_error": 0.0, + "category": "graduate_or_professional_degree", + "estimate": 209506.98346852517, + "estimate_share": 0.09737368370084203, + "households": 183, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.49.graduate_or_professional_degree.population", + "records": 214, + "relative_error": -0.2880063364694272, + "share_error_pp": -3.9284988677622796, + "state": "UT", + "state_fips": "49", + "target": 294254.0, + "target_share": 0.13665867237846482 + }, + { + "calibrated_relative_error": 1.7392309814567852e-11, + "category": "less_than_9th_grade", + "estimate": 6349.471716000322, + "estimate_share": 0.01344959223959153, + "households": 3, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.50.less_than_9th_grade.population", + "records": 4, + "relative_error": -0.2896888112763931, + "share_error_pp": -0.5395261844022364, + "state": "VT", + "state_fips": "50", + "target": 8939.0, + "target_share": 0.018844854083613895 + }, + { + "calibrated_relative_error": 3.2304736663490985e-10, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 17115.45864952117, + "estimate_share": 0.036254345263019044, + "households": 18, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.50.9th_to_12th_grade_no_diploma.population", + "records": 21, + "relative_error": 0.05820815194269624, + "share_error_pp": 0.21569439934842963, + "state": "VT", + "state_fips": "50", + "target": 16174.0, + "target_share": 0.03409740126953475 + }, + { + "calibrated_relative_error": 2.57569743311592e-10, + "category": "high_school_graduate_includes_equivalency", + "estimate": 131796.75846955183, + "estimate_share": 0.2791748257494425, + "households": 175, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.50.high_school_graduate_includes_equivalency.population", + "records": 237, + "relative_error": 0.07677969974878751, + "share_error_pp": 2.1137987738450548, + "state": "VT", + "state_fips": "50", + "target": 122399.0, + "target_share": 0.258036838010992 + }, + { + "calibrated_relative_error": 2.0209980355900825e-09, + "category": "some_college_no_degree", + "estimate": 45957.82178797772, + "estimate_share": 0.09734888049197893, + "households": 75, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.50.some_college_no_degree.population", + "records": 79, + "relative_error": -0.35863260874207714, + "share_error_pp": -5.37135274077232, + "state": "VT", + "state_fips": "50", + "target": 71656.0, + "target_share": 0.15106240789970213 + }, + { + "calibrated_relative_error": 2.28721486195127e-10, + "category": "associates_degree", + "estimate": 43239.59235559637, + "estimate_share": 0.09159106643840048, + "households": 81, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.50.associates_degree.population", + "records": 93, + "relative_error": 0.04780072105063038, + "share_error_pp": 0.45935730422158316, + "state": "VT", + "state_fips": "50", + "target": 41267.0, + "target_share": 0.08699749339618465 + }, + { + "calibrated_relative_error": 2.7252622381013225e-10, + "category": "bachelors_degree", + "estimate": 148190.31420459555, + "estimate_share": 0.31390002019951635, + "households": 213, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.50.bachelors_degree.population", + "records": 274, + "relative_error": 0.20741045027942984, + "share_error_pp": 5.515694814467043, + "state": "VT", + "state_fips": "50", + "target": 122734.0, + "target_share": 0.2587430720548459 + }, + { + "calibrated_relative_error": 7.445732919109105e-11, + "category": "graduate_or_professional_degree", + "estimate": 79444.57666360379, + "estimate_share": 0.16828126961805112, + "households": 121, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.50.graduate_or_professional_degree.population", + "records": 151, + "relative_error": -0.12868700055272342, + "share_error_pp": -2.3936663667075586, + "state": "VT", + "state_fips": "50", + "target": 91178.0, + "target_share": 0.1922179332851267 + }, + { + "calibrated_relative_error": 4.556355293061642e-13, + "category": "less_than_9th_grade", + "estimate": 183003.80861560634, + "estimate_share": 0.029941753817051324, + "households": 74, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.51.less_than_9th_grade.population", + "records": 113, + "relative_error": -0.19724961238224892, + "share_error_pp": -0.7352114094821872, + "state": "VA", + "state_fips": "51", + "target": 227971.0, + "target_share": 0.037293867911873196 + }, + { + "calibrated_relative_error": 2.928768338961163e-13, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 222676.3304321528, + "estimate_share": 0.036432683653531965, + "households": 74, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.51.9th_to_12th_grade_no_diploma.population", + "records": 90, + "relative_error": -0.20105796468009207, + "share_error_pp": -0.9162252111060136, + "state": "VA", + "state_fips": "51", + "target": 278714.0, + "target_share": 0.0455949357645921 + }, + { + "calibrated_relative_error": 2.2040147484858608e-12, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1252349.6876938425, + "estimate_share": 0.20490035877096166, + "households": 463, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.51.high_school_graduate_includes_equivalency.population", + "records": 633, + "relative_error": -0.13236852146591382, + "share_error_pp": -3.1227992951023658, + "state": "VA", + "state_fips": "51", + "target": 1443412.0, + "target_share": 0.23612835172198532 + }, + { + "calibrated_relative_error": 1.935340776526573e-12, + "category": "some_college_no_degree", + "estimate": 874372.7424132875, + "estimate_share": 0.14305851662721114, + "households": 264, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.51.some_college_no_degree.population", + "records": 311, + "relative_error": -0.15751367983241527, + "share_error_pp": -2.6723456626412236, + "state": "VA", + "state_fips": "51", + "target": 1037848.0, + "target_share": 0.16978197325362337 + }, + { + "calibrated_relative_error": 1.3558043576722412e-12, + "category": "associates_degree", + "estimate": 464013.10751712765, + "estimate_share": 0.0759184540379997, + "households": 212, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.51.associates_degree.population", + "records": 244, + "relative_error": -0.024159554833475316, + "share_error_pp": -0.18689464908553666, + "state": "VA", + "state_fips": "51", + "target": 475501.0, + "target_share": 0.07778740052885506 + }, + { + "calibrated_relative_error": 2.311084656980711e-11, + "category": "bachelors_degree", + "estimate": 1971093.9227999605, + "estimate_share": 0.32249606952567766, + "households": 544, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.51.bachelors_degree.population", + "records": 718, + "relative_error": 0.3355434968025457, + "share_error_pp": 8.105724612020968, + "state": "VA", + "state_fips": "51", + "target": 1475874.0, + "target_share": 0.241438823405468 + }, + { + "calibrated_relative_error": 2.084554751036194e-12, + "category": "graduate_or_professional_degree", + "estimate": 1144484.0310209955, + "estimate_share": 0.18725216356756663, + "households": 434, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.51.graduate_or_professional_degree.population", + "records": 554, + "relative_error": -0.024732655404994697, + "share_error_pp": -0.47224838460363794, + "state": "VA", + "state_fips": "51", + "target": 1173508.0, + "target_share": 0.191974647413603 + }, + { + "calibrated_relative_error": 0.0, + "category": "less_than_9th_grade", + "estimate": 276898.5917862904, + "estimate_share": 0.049228430951029946, + "households": 59, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.53.less_than_9th_grade.population", + "records": 92, + "relative_error": 0.46828037874450734, + "share_error_pp": 1.5740312416937545, + "state": "WA", + "state_fips": "53", + "target": 188587.0, + "target_share": 0.0334881185340924 + }, + { + "calibrated_relative_error": -4.440892098500626e-16, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 189057.0015736815, + "estimate_share": 0.03361150913675228, + "households": 86, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.53.9th_to_12th_grade_no_diploma.population", + "records": 99, + "relative_error": -0.23404435703967785, + "share_error_pp": -1.0218154929049483, + "state": "WA", + "state_fips": "53", + "target": 246825.0, + "target_share": 0.043829664065801764 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1394298.8630456736, + "estimate_share": 0.24788549794257897, + "households": 399, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.53.high_school_graduate_includes_equivalency.population", + "records": 550, + "relative_error": 0.17483993755107097, + "share_error_pp": 3.714103735864513, + "state": "WA", + "state_fips": "53", + "target": 1186799.0, + "target_share": 0.21074446058393384 + }, + { + "calibrated_relative_error": 0.0, + "category": "some_college_no_degree", + "estimate": 935083.1058243812, + "estimate_share": 0.16624379998320135, + "households": 289, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.53.some_college_no_degree.population", + "records": 364, + "relative_error": -0.1678645334231712, + "share_error_pp": -3.3298592220596586, + "state": "WA", + "state_fips": "53", + "target": 1123715.0, + "target_share": 0.19954239220379794 + }, + { + "calibrated_relative_error": 4.440892098500626e-16, + "category": "associates_degree", + "estimate": 641058.1505200323, + "estimate_share": 0.1139705575780861, + "households": 236, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.53.associates_degree.population", + "records": 269, + "relative_error": 0.11358423564854281, + "share_error_pp": 1.1746445180945753, + "state": "WA", + "state_fips": "53", + "target": 575671.0, + "target_share": 0.10222411239714035 + }, + { + "calibrated_relative_error": 0.0, + "category": "bachelors_degree", + "estimate": 1382441.1405773805, + "estimate_share": 0.2457773721193268, + "households": 507, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.53.bachelors_degree.population", + "records": 656, + "relative_error": 0.006930556036800706, + "share_error_pp": 0.19816246577449015, + "state": "WA", + "state_fips": "53", + "target": 1372926.0, + "target_share": 0.2437957474615819 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "graduate_or_professional_degree", + "estimate": 805932.9481260269, + "estimate_share": 0.14328283228902453, + "households": 362, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.53.graduate_or_professional_degree.population", + "records": 452, + "relative_error": -0.13982162287749667, + "share_error_pp": -2.309267246462729, + "state": "WA", + "state_fips": "53", + "target": 936937.0, + "target_share": 0.16637550475365182 + }, + { + "calibrated_relative_error": 2.7928992452075363e-11, + "category": "less_than_9th_grade", + "estimate": 27241.146787697697, + "estimate_share": 0.021530675694149782, + "households": 13, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.54.less_than_9th_grade.population", + "records": 14, + "relative_error": -0.29118581422518486, + "share_error_pp": -0.8762012269567094, + "state": "WV", + "state_fips": "54", + "target": 38432.0, + "target_share": 0.030292687963716876 + }, + { + "calibrated_relative_error": 1.1166623181679824e-12, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 85967.7048082293, + "estimate_share": 0.06794658047334062, + "households": 83, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.54.9th_to_12th_grade_no_diploma.population", + "records": 91, + "relative_error": -0.01802818166187714, + "share_error_pp": -0.10585106088710078, + "state": "WV", + "state_fips": "54", + "target": 87546.0, + "target_share": 0.06900509108221163 + }, + { + "calibrated_relative_error": 3.2507330161024584e-13, + "category": "high_school_graduate_includes_equivalency", + "estimate": 560235.8525189675, + "estimate_share": 0.44279547211532294, + "households": 449, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.54.high_school_graduate_includes_equivalency.population", + "records": 662, + "relative_error": 0.12132166686141588, + "share_error_pp": 4.898658751082174, + "state": "WV", + "state_fips": "54", + "target": 499621.0, + "target_share": 0.3938088846045012 + }, + { + "calibrated_relative_error": 2.55351295663786e-14, + "category": "some_college_no_degree", + "estimate": 210424.01319295715, + "estimate_share": 0.16631352643219466, + "households": 178, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.54.some_college_no_degree.population", + "records": 211, + "relative_error": -0.07513245900123444, + "share_error_pp": -1.301962771354162, + "state": "WV", + "state_fips": "54", + "target": 227518.0, + "target_share": 0.17933315414573628 + }, + { + "calibrated_relative_error": 2.298161660974074e-13, + "category": "associates_degree", + "estimate": 138481.04532499285, + "estimate_share": 0.10945172389092615, + "households": 170, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.54.associates_degree.population", + "records": 189, + "relative_error": 0.30284826866802317, + "share_error_pp": 2.5671538203180773, + "state": "WV", + "state_fips": "54", + "target": 106291.0, + "target_share": 0.08378018568774538 + }, + { + "calibrated_relative_error": 1.3078427230084344e-13, + "category": "bachelors_degree", + "estimate": 151166.5656918272, + "estimate_share": 0.1194780207703655, + "households": 199, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.54.bachelors_degree.population", + "records": 242, + "relative_error": -0.19469743497114111, + "share_error_pp": -2.8481014107370486, + "state": "WV", + "state_fips": "54", + "target": 187714.0, + "target_share": 0.14795903487773598 + }, + { + "calibrated_relative_error": 8.208989044078407e-13, + "category": "graduate_or_professional_degree", + "estimate": 91708.56171905035, + "estimate_share": 0.07248400062370035, + "households": 126, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.54.graduate_or_professional_degree.population", + "records": 160, + "relative_error": -0.2456130222918197, + "share_error_pp": -2.333696101465231, + "state": "WV", + "state_fips": "54", + "target": 121567.0, + "target_share": 0.09582096163835266 + }, + { + "calibrated_relative_error": -1.1102230246251565e-16, + "category": "less_than_9th_grade", + "estimate": 127895.4850785971, + "estimate_share": 0.030781131059838, + "households": 36, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.55.less_than_9th_grade.population", + "records": 54, + "relative_error": 0.29076535377299395, + "share_error_pp": 0.7034762455612086, + "state": "WI", + "state_fips": "55", + "target": 99085.0, + "target_share": 0.023746368604225913 + }, + { + "calibrated_relative_error": 1.3322676295501878e-15, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 62409.63317744875, + "estimate_share": 0.01502038244001268, + "households": 57, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.55.9th_to_12th_grade_no_diploma.population", + "records": 70, + "relative_error": -0.617583345522318, + "share_error_pp": -2.409108613214719, + "state": "WI", + "state_fips": "55", + "target": 163198.0, + "target_share": 0.039111468572159865 + }, + { + "calibrated_relative_error": 0.0, + "category": "high_school_graduate_includes_equivalency", + "estimate": 1289217.8879144536, + "estimate_share": 0.31028135784617505, + "households": 447, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.55.high_school_graduate_includes_equivalency.population", + "records": 600, + "relative_error": 0.07213160782952377, + "share_error_pp": 2.209891786456153, + "state": "WI", + "state_fips": "55", + "target": 1202481.0, + "target_share": 0.2881824399816135 + }, + { + "calibrated_relative_error": -3.3306690738754696e-16, + "category": "some_college_no_degree", + "estimate": 548909.6420080569, + "estimate_share": 0.1321083353354923, + "households": 248, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.55.some_college_no_degree.population", + "records": 274, + "relative_error": -0.29742623423997305, + "share_error_pp": -5.513148752956335, + "state": "WI", + "state_fips": "55", + "target": 781284.0, + "target_share": 0.18723982286505564 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "associates_degree", + "estimate": 754411.2967434262, + "estimate_share": 0.1815672616106118, + "households": 272, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.55.associates_degree.population", + "records": 315, + "relative_error": 0.5564692295415794, + "share_error_pp": 6.540717295686325, + "state": "WI", + "state_fips": "55", + "target": 484694.0, + "target_share": 0.11616008865374854 + }, + { + "calibrated_relative_error": -2.220446049250313e-16, + "category": "bachelors_degree", + "estimate": 934434.2600260542, + "estimate_share": 0.22489412669249964, + "households": 433, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.55.bachelors_degree.population", + "records": 552, + "relative_error": -0.00929466781093935, + "share_error_pp": -0.11501647126018755, + "state": "WI", + "state_fips": "55", + "target": 943201.0, + "target_share": 0.22604429140510152 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "graduate_or_professional_degree", + "estimate": 437718.0760518535, + "estimate_share": 0.10534740501537046, + "households": 258, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.55.graduate_or_professional_degree.population", + "records": 320, + "relative_error": -0.12227298037507195, + "share_error_pp": -1.4168114902724516, + "state": "WI", + "state_fips": "55", + "target": 498695.0, + "target_share": 0.11951551991809498 + }, + { + "calibrated_relative_error": 2.3165913631828516e-12, + "category": "less_than_9th_grade", + "estimate": 2969.7837420582205, + "estimate_share": 0.007327948544575399, + "households": 11, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.56.less_than_9th_grade.population", + "records": 15, + "relative_error": -0.6599354469187885, + "share_error_pp": -1.4006186070809217, + "state": "WY", + "state_fips": "56", + "target": 8733.0, + "target_share": 0.021334134615384616 + }, + { + "calibrated_relative_error": 6.854516954035716e-13, + "category": "9th_to_12th_grade_no_diploma", + "estimate": 14114.748830389772, + "estimate_share": 0.034828176773914844, + "households": 25, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.56.9th_to_12th_grade_no_diploma.population", + "records": 31, + "relative_error": 0.0012590501801639231, + "share_error_pp": 0.03901491003688792, + "state": "WY", + "state_fips": "56", + "target": 14097.0, + "target_share": 0.034438027673545965 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "high_school_graduate_includes_equivalency", + "estimate": 115645.69850736058, + "estimate_share": 0.2853560399236655, + "households": 200, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.56.high_school_graduate_includes_equivalency.population", + "records": 265, + "relative_error": 0.01242885601667365, + "share_error_pp": 0.6309565564691144, + "state": "WY", + "state_fips": "56", + "target": 114226.0, + "target_share": 0.27904647435897434 + }, + { + "calibrated_relative_error": 1.0103029524088925e-13, + "category": "some_college_no_degree", + "estimate": 75448.6296264111, + "estimate_share": 0.18616967553263297, + "households": 173, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.56.some_college_no_degree.population", + "records": 203, + "relative_error": -0.2189097705197931, + "share_error_pp": -4.980300270376478, + "state": "WY", + "state_fips": "56", + "target": 96594.0, + "target_share": 0.23597267823639775 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "associates_degree", + "estimate": 51863.672725974626, + "estimate_share": 0.12797373751034222, + "households": 108, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.56.associates_degree.population", + "records": 120, + "relative_error": 0.19106358455756545, + "share_error_pp": 2.1598659336483554, + "state": "WY", + "state_fips": "56", + "target": 43544.0, + "target_share": 0.10637507817385866 + }, + { + "calibrated_relative_error": -3.3306690738754696e-16, + "category": "bachelors_degree", + "estimate": 92474.92505131518, + "estimate_share": 0.22818210054913124, + "households": 179, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.56.bachelors_degree.population", + "records": 221, + "relative_error": 0.11525754421615542, + "share_error_pp": 2.5618975158261947, + "state": "WY", + "state_fips": "56", + "target": 82918.0, + "target_share": 0.2025631253908693 + }, + { + "calibrated_relative_error": 2.220446049250313e-16, + "category": "graduate_or_professional_degree", + "estimate": 52750.63585329348, + "estimate_share": 0.13016232116573784, + "households": 113, + "name": "census_acs.acs1_2024.s1501.state_attainment_25_plus.56.graduate_or_professional_degree.population", + "records": 145, + "relative_error": 0.07147050400742372, + "share_error_pp": 0.9891839614768485, + "state": "WY", + "state_fips": "56", + "target": 49232.0, + "target_share": 0.12027048155096935 + } + ], + "share_error_pp_max_abs": 10.843839687879026, + "share_error_pp_mean_abs": 2.2925318867749804, + "share_error_pp_p90_abs": 5.208897156314941 + }, + "commit": "e2621e231c6cbc62939711e7c967be314624f65c", + "generated_at": "2026-10-22T17:33:13+00:00", + "held_out_18_to_24": { + "national_by_category": { + "bachelors_degree_or_higher": -1.2832979570529888, + "high_school_graduate_includes_equivalency": -3.963187275952528, + "less_than_high_school_graduate": 2.427848758285743, + "some_college_or_associates_degree": 2.8186364747197743 + }, + "reason": "Not compiled: the ACS counts college students in dormitories (group quarters) in the state of their college, the CPS in their parents' household.", + "share_error_pp_max_abs": 34.030114363598244, + "share_error_pp_mean_abs": 6.806574553318915 + }, + "host": { + "households": 57240, + "path": "populace_us_2024.h5", + "persons": 166321, + "release": "populace-us-2024-spm-20260915", + "sha256": "6496cc4393d4d3c6574f76eca231de5898c803b9067645591fd5c4d3e65aee84" + }, + "issue": "PolicyEngine/microcosm#297", + "modal_run": "20261022T171517Z-e2621e231", + "national_25_plus": { + "9th_to_12th_grade_no_diploma": { + "estimate": 11697364.928681675, + "estimate_share": 0.04965592943812166, + "target": 12868166.0, + "target_share": 0.054546762667447936 + }, + "associates_degree": { + "estimate": 26239079.785795875, + "estimate_share": 0.11138627394362804, + "target": 20848519.0, + "target_share": 0.08837461514413002 + }, + "bachelors_degree": { + "estimate": 57038622.67389197, + "estimate_share": 0.24213195365031961, + "target": 52233014.0, + "target_share": 0.22141009201027445 + }, + "graduate_or_professional_degree": { + "estimate": 33791865.71889394, + "estimate_share": 0.14344824752842783, + "target": 34699683.0, + "target_share": 0.14708819992193742 + }, + "high_school_graduate_includes_equivalency": { + "estimate": 65687585.933326, + "estimate_share": 0.2788472576475734, + "target": 60698932.0, + "target_share": 0.2572962019585045 + }, + "less_than_9th_grade": { + "estimate": 7818957.936073032, + "estimate_share": 0.0331918877388603, + "target": 10908872.0, + "target_share": 0.046241527499223126 + }, + "some_college_no_degree": { + "estimate": 33294864.227347277, + "estimate_share": 0.1413384500530691, + "target": 43653533.0, + "target_share": 0.1850426007984826 + } + }, + "roi_classes": { + "baseline": { + "class": "high_school_graduate_includes_equivalency", + "records_min": 95, + "relative_error_median_abs": 0.08471182355367968, + "share_error_pp_max_abs": 10.843839687879026, + "share_error_pp_mean_abs": 2.86921508520404 + }, + "four_year_degree": { + "class": "bachelors_degree", + "records_min": 221, + "relative_error_median_abs": 0.08719415313060375, + "share_error_pp_max_abs": 8.105724612020968, + "share_error_pp_mean_abs": 2.3243239160686024 + }, + "two_year_degree": { + "class": "associates_degree", + "records_min": 21, + "relative_error_median_abs": 0.19174079962260193, + "share_error_pp_max_abs": 7.287363263994082, + "share_error_pp_mean_abs": 2.44584744618573 + } + }, + "s1501": { + "compiled_targets": 357, + "facts": 676, + "facts_sha256": "97a049688b7f84cad3c9c2da97e50d1dc491a142584e423f24b8a46dd80e5cd4", + "max_abs_partition_gap": 0.0, + "raw_sha256": "84fff08c9d2793a90f2326eb68ae8ba4d5e18957899fc8cdda015d26520f73a4", + "raw_value_mismatches": [], + "source": "https://github.com/DTrim99/chronicle.git@81e3f986ccc47571a427a4adda8d4b49560d03bf:packages/census/acs_s1501_state_2024 (TEMPORARY draft input: PolicyEngine/chronicle#347 (fork DTrim99/chronicle))", + "status": "TEMPORARY draft input: PolicyEngine/chronicle#347 is unmerged" + }, + "schema_version": 1, + "sidecar": { + "columns": [ + "person_id", + "A_HGA", + "cps_educational_attainment" + ], + "file": "populace_us_2024_cps_educational_attainment.csv.gz", + "rows": 166321, + "sha256": "34994413e255524f16ab9d985bd8ca8470deab1149b3ee395d2ee307c9d7e62b" + }, + "stage": { + "derivation": { + "class_rows": { + "9th_to_12th_grade_no_diploma": 14123, + "associates_degree": 12238, + "bachelors_degree": 27335, + "graduate_or_professional_degree": 17929, + "high_school_graduate_includes_equivalency": 33552, + "less_than_9th_grade": 5216, + "not_in_universe": 37248, + "some_college_no_degree": 18680 + }, + "column": "cps_educational_attainment", + "column_role": "auxiliary", + "columns_added": [ + "A_HGA", + "cps_educational_attainment" + ], + "identity_columns_verified": { + "A_AGE": 166321, + "A_LINENO": 166321, + "P_SEQ": 166321, + "source_household_id": 166321 + }, + "join_key": "(source_year, PERIDNUM); many persons to one member row", + "joined_persons_by_income_year": { + "2022": 54464, + "2023": 54654, + "2024": 57203 + }, + "operation": "exact_source_join", + "source_column": "A_HGA", + "sources": { + "2022": { + "a_hga_counts": { + "0": 29483, + "31": 330, + "32": 676, + "33": 1424, + "34": 2529, + "35": 3130, + "36": 3571, + "37": 3904, + "38": 2009, + "39": 32029, + "40": 17865, + "41": 4691, + "42": 6342, + "43": 23640, + "44": 10784, + "45": 1553, + "46": 2173 + }, + "archive_sha256": "d2e000250782adfbdd7f29c82b66d866591a30f0d330496698ec19f9c784ce11", + "income_year": 2022, + "member": "pppub23.csv", + "member_sha256": "19b56537e50e7663f954361ef2bb5ce9cef8d9d45f156fe1a69a99b654198ffe", + "official_archive_url": "https://www2.census.gov/programs-surveys/cps/datasets/2023/march/asecpub23csv.zip", + "persons": 146133, + "source_form": "archive", + "survey_year": 2023 + }, + "2023": { + "a_hga_counts": { + "0": 28429, + "31": 348, + "32": 699, + "33": 1386, + "34": 2419, + "35": 3167, + "36": 3390, + "37": 3596, + "38": 2032, + "39": 31777, + "40": 17234, + "41": 4984, + "42": 6469, + "43": 23780, + "44": 10879, + "45": 1428, + "46": 2248 + }, + "archive_sha256": "cdb39cdac34bef99dd0940ab28e306f692404c2eea44d85dfd634214872a0a09", + "income_year": 2023, + "member": "pppub24.csv", + "member_sha256": "21a2b9e0e4b08534563578a45acad77868af4ae9a7d46f23776b707d4a559aa7", + "official_archive_url": "https://www2.census.gov/programs-surveys/cps/datasets/2024/march/asecpub24csv.zip", + "persons": 144265, + "source_form": "archive", + "survey_year": 2024 + }, + "2024": { + "a_hga_counts": { + "0": 27679, + "31": 346, + "32": 621, + "33": 1236, + "34": 2284, + "35": 2962, + "36": 3408, + "37": 3565, + "38": 2136, + "39": 31102, + "40": 16841, + "41": 4860, + "42": 6497, + "43": 23784, + "44": 10921, + "45": 1488, + "46": 2395 + }, + "archive_sha256": "318845a2b5e0034eb2973898de1738f4df0025727de38499e7669cb9c0deef0b", + "income_year": 2024, + "member": "pppub25.csv", + "member_sha256": "06921fe83fc66c907e6c7b86b82255dc70458ee7d76258fc48297cb34f0c06b5", + "official_archive_url": "https://www2.census.gov/programs-surveys/cps/datasets/2025/march/asecpub25csv.zip", + "persons": 142125, + "source_form": "archive", + "survey_year": 2025 + } + } + }, + "signal_gate": { + "bachelors_or_higher_share_25_plus": 0.3855802011787475, + "bachelors_or_higher_share_band": [ + 0.25, + 0.45 + ], + "less_than_high_school_share_25_plus": 0.08284781717698197, + "less_than_high_school_share_band": [ + 0.05, + 0.16 + ], + "missing_values": 0, + "persons": 166321, + "rows_by_class": { + "9th_to_12th_grade_no_diploma": 14123, + "associates_degree": 12238, + "bachelors_degree": 27335, + "graduate_or_professional_degree": 17929, + "high_school_graduate_includes_equivalency": 33552, + "less_than_9th_grade": 5216, + "not_in_universe": 37248, + "some_college_no_degree": 18680 + }, + "share_25_plus_by_class": { + "9th_to_12th_grade_no_diploma": 0.04965592943812166, + "associates_degree": 0.11138627394362804, + "bachelors_degree": 0.24213195365031964, + "graduate_or_professional_degree": 0.14344824752842786, + "high_school_graduate_includes_equivalency": 0.2788472576475734, + "less_than_9th_grade": 0.03319188773886031, + "not_in_universe": 0.0, + "some_college_no_degree": 0.1413384500530691 + }, + "universe_disagreements": 0, + "unknown_values": 0, + "weighted_population": 340077322.65364885, + "weighted_population_25_plus": 235568341.20400977 + }, + "signal_gate_failures": [], + "signal_gate_passed": true + }, + "standalone_calibration": { + "by_state": { + "AK": { + "iterations": 7, + "kish_ess_after": 112.32951768182893, + "kish_ess_before": 133.09802879677864, + "max_abs_relative_error": 1.8197575398335708e-11, + "state_population_change": 0.0006617216013919958, + "weight_ratio_max": 20.911896228201652, + "weight_ratio_min": 0.32284616626242524, + "weight_ratio_p01": 0.42908134842584184, + "weight_ratio_p50": 1.0263364704890883, + "weight_ratio_p99": 3.291366310900928 + }, + "AL": { + "iterations": 5, + "kish_ess_after": 228.58996025377562, + "kish_ess_before": 236.55107319475567, + "max_abs_relative_error": 5.02308171514538e-12, + "state_population_change": 0.0011444351738620906, + "weight_ratio_max": 1.6318805596353854, + "weight_ratio_min": 0.4993748734795688, + "weight_ratio_p01": 0.7799518131546759, + "weight_ratio_p50": 1.015954295987476, + "weight_ratio_p99": 1.3099395995336713 + }, + "AR": { + "iterations": 6, + "kish_ess_after": 188.07039239540714, + "kish_ess_before": 205.8083941145262, + "max_abs_relative_error": 9.183080434659645e-12, + "state_population_change": 0.00011869113982898583, + "weight_ratio_max": 7.27098816821411, + "weight_ratio_min": 0.4396149161952401, + "weight_ratio_p01": 0.5904510518507994, + "weight_ratio_p50": 0.9780806248119494, + "weight_ratio_p99": 5.38290582442243 + }, + "AZ": { + "iterations": 8, + "kish_ess_after": 175.6830470454704, + "kish_ess_before": 189.9592184041849, + "max_abs_relative_error": 3.926738253655655e-16, + "state_population_change": 0.0009294832235338113, + "weight_ratio_max": 2.9742535255904263, + "weight_ratio_min": 0.3728938280110393, + "weight_ratio_p01": 0.5180720110885044, + "weight_ratio_p50": 0.9541607472391407, + "weight_ratio_p99": 2.068165662776604 + }, + "CA": { + "iterations": 6, + "kish_ess_after": 930.0903025565257, + "kish_ess_before": 964.8602100502725, + "max_abs_relative_error": 6.641855772420808e-14, + "state_population_change": 0.00047429802880838423, + "weight_ratio_max": 3.188758523327037, + "weight_ratio_min": 0.4282216721046277, + "weight_ratio_p01": 0.633784644279457, + "weight_ratio_p50": 0.9191762772038317, + "weight_ratio_p99": 1.8921221774726924 + }, + "CO": { + "iterations": 5, + "kish_ess_after": 142.938316230397, + "kish_ess_before": 145.44069869412928, + "max_abs_relative_error": 2.37763113659529e-12, + "state_population_change": 0.001847846871019465, + "weight_ratio_max": 2.0964330532273556, + "weight_ratio_min": 0.6542347776408833, + "weight_ratio_p01": 0.7552122348103354, + "weight_ratio_p50": 0.9401396240164366, + "weight_ratio_p99": 1.6926632957963499 + }, + "CT": { + "iterations": 6, + "kish_ess_after": 124.95433355384571, + "kish_ess_before": 135.72407292141725, + "max_abs_relative_error": 6.909200004922146e-15, + "state_population_change": 0.0014023499588440291, + "weight_ratio_max": 4.190345469313615, + "weight_ratio_min": 0.4984071514334719, + "weight_ratio_p01": 0.6029820200374232, + "weight_ratio_p50": 0.9005710605527174, + "weight_ratio_p99": 2.7752706658914996 + }, + "DC": { + "iterations": 6, + "kish_ess_after": 173.0334687584342, + "kish_ess_before": 175.55582471377855, + "max_abs_relative_error": 1.9206223354641687e-14, + "state_population_change": 0.027875308000811616, + "weight_ratio_max": 2.053854327230436, + "weight_ratio_min": 0.36729144526251567, + "weight_ratio_p01": 0.5752717462709755, + "weight_ratio_p50": 0.9887256202120085, + "weight_ratio_p99": 2.018744837639689 + }, + "DE": { + "iterations": 12, + "kish_ess_after": 134.18041264810586, + "kish_ess_before": 138.95841520788005, + "max_abs_relative_error": 7.673308283973288e-16, + "state_population_change": -0.0009560740240781573, + "weight_ratio_max": 2.833481856451399, + "weight_ratio_min": 0.6680539317850803, + "weight_ratio_p01": 0.738939093139403, + "weight_ratio_p50": 0.9188587721993006, + "weight_ratio_p99": 2.0263185882927672 + }, + "FL": { + "iterations": 6, + "kish_ess_after": 518.3755083652455, + "kish_ess_before": 561.2687931315957, + "max_abs_relative_error": 1.176367558610299e-14, + "state_population_change": 0.00016919331715747887, + "weight_ratio_max": 4.053139002179033, + "weight_ratio_min": 0.5981422392859811, + "weight_ratio_p01": 0.6766160747906743, + "weight_ratio_p50": 0.8841762300944127, + "weight_ratio_p99": 2.0132409200537906 + }, + "GA": { + "iterations": 6, + "kish_ess_after": 231.0171598659535, + "kish_ess_before": 256.7233154812113, + "max_abs_relative_error": 6.354618451716608e-13, + "state_population_change": 0.001450743319011849, + "weight_ratio_max": 5.630456203815779, + "weight_ratio_min": 0.46981027015504967, + "weight_ratio_p01": 0.6236677935471238, + "weight_ratio_p50": 0.8976612049767666, + "weight_ratio_p99": 2.478886234985681 + }, + "HI": { + "iterations": 7, + "kish_ess_after": 163.1177991844619, + "kish_ess_before": 197.42767354447827, + "max_abs_relative_error": 4.650194894170019e-14, + "state_population_change": 0.0008507794309535743, + "weight_ratio_max": 19.189374045143946, + "weight_ratio_min": 0.26884154399638927, + "weight_ratio_p01": 0.4357630053873101, + "weight_ratio_p50": 0.8396321035391654, + "weight_ratio_p99": 5.9437218808502275 + }, + "IA": { + "iterations": 7, + "kish_ess_after": 134.76518942968653, + "kish_ess_before": 138.47468958011123, + "max_abs_relative_error": 4.316810794571873e-16, + "state_population_change": 0.0024242881879961153, + "weight_ratio_max": 2.1110464600285344, + "weight_ratio_min": 0.2229231415567611, + "weight_ratio_p01": 0.48003506346267, + "weight_ratio_p50": 0.9793170520403944, + "weight_ratio_p99": 1.644130781082292 + }, + "ID": { + "iterations": 5, + "kish_ess_after": 180.3374844778537, + "kish_ess_before": 185.13141307532993, + "max_abs_relative_error": 2.2861873372887988e-12, + "state_population_change": 0.0008170788604988655, + "weight_ratio_max": 1.851591813642149, + "weight_ratio_min": 0.6200318934745598, + "weight_ratio_p01": 0.6939576893866464, + "weight_ratio_p50": 1.0263670351071996, + "weight_ratio_p99": 1.7573067591538962 + }, + "IL": { + "iterations": 5, + "kish_ess_after": 271.5839613779876, + "kish_ess_before": 276.79640609431533, + "max_abs_relative_error": 3.576467820841008e-13, + "state_population_change": 0.0009655136396433672, + "weight_ratio_max": 2.166517884314565, + "weight_ratio_min": 0.5100370272831161, + "weight_ratio_p01": 0.6393563800835427, + "weight_ratio_p50": 0.9911888438577314, + "weight_ratio_p99": 1.4992695876910795 + }, + "IN": { + "iterations": 6, + "kish_ess_after": 172.75902710440994, + "kish_ess_before": 177.01966696059426, + "max_abs_relative_error": 3.3072910438452374e-16, + "state_population_change": 0.00272171777607344, + "weight_ratio_max": 2.3218357235194507, + "weight_ratio_min": 0.6412623750777058, + "weight_ratio_p01": 0.7807388872447382, + "weight_ratio_p50": 0.9480724201747299, + "weight_ratio_p99": 1.7697985669331444 + }, + "KS": { + "iterations": 6, + "kish_ess_after": 147.28636288330196, + "kish_ess_before": 148.6054105840971, + "max_abs_relative_error": 3.575963228578084e-14, + "state_population_change": 0.005235892104836104, + "weight_ratio_max": 4.219413332788855, + "weight_ratio_min": 0.42765406578282483, + "weight_ratio_p01": 0.5972206388126298, + "weight_ratio_p50": 1.00498660493315, + "weight_ratio_p99": 1.8598627116347743 + }, + "KY": { + "iterations": 6, + "kish_ess_after": 117.18251935453688, + "kish_ess_before": 129.52044465545663, + "max_abs_relative_error": 3.5216628452321978e-12, + "state_population_change": 0.0006855951959476858, + "weight_ratio_max": 7.28914479344038, + "weight_ratio_min": 0.3211258971932955, + "weight_ratio_p01": 0.3804299124992997, + "weight_ratio_p50": 1.0013770351797788, + "weight_ratio_p99": 2.799239394765385 + }, + "LA": { + "iterations": 7, + "kish_ess_after": 242.21286960655524, + "kish_ess_before": 260.90086270703296, + "max_abs_relative_error": 2.5102709577220523e-16, + "state_population_change": 0.0016819472448830197, + "weight_ratio_max": 130.9713001422298, + "weight_ratio_min": 0.4793309389751094, + "weight_ratio_p01": 0.4942632242915125, + "weight_ratio_p50": 1.0206392651870275, + "weight_ratio_p99": 2.26119417167763 + }, + "MA": { + "iterations": 7, + "kish_ess_after": 236.2140570627537, + "kish_ess_before": 254.60923423077767, + "max_abs_relative_error": 5.351477216016838e-16, + "state_population_change": 0.0010444939657463514, + "weight_ratio_max": 9.419832302277287, + "weight_ratio_min": 0.37162613023091445, + "weight_ratio_p01": 0.4528814693783661, + "weight_ratio_p50": 0.9699161641577138, + "weight_ratio_p99": 2.3097683683479704 + }, + "MD": { + "iterations": 6, + "kish_ess_after": 132.13169471840354, + "kish_ess_before": 142.9724839367435, + "max_abs_relative_error": 8.04398192601304e-16, + "state_population_change": 0.0014904240744015862, + "weight_ratio_max": 5.1321228737484414, + "weight_ratio_min": 0.3180169230546092, + "weight_ratio_p01": 0.4659079855242381, + "weight_ratio_p50": 1.0401140056989118, + "weight_ratio_p99": 2.242273058398092 + }, + "ME": { + "iterations": 6, + "kish_ess_after": 88.77161059449492, + "kish_ess_before": 98.94461640482403, + "max_abs_relative_error": 7.682941243185416e-13, + "state_population_change": 0.0035653486839968274, + "weight_ratio_max": 3.057345242899663, + "weight_ratio_min": 0.5234080388924394, + "weight_ratio_p01": 0.5646529250143164, + "weight_ratio_p50": 0.8900905998754779, + "weight_ratio_p99": 2.8316681014158207 + }, + "MI": { + "iterations": 6, + "kish_ess_after": 225.96150428813618, + "kish_ess_before": 244.58681076309966, + "max_abs_relative_error": 6.105467874239972e-16, + "state_population_change": 0.0009617707724043356, + "weight_ratio_max": 3.6873574696327767, + "weight_ratio_min": 0.37042971421300525, + "weight_ratio_p01": 0.6041424559017277, + "weight_ratio_p50": 0.945471538626517, + "weight_ratio_p99": 1.9202493248619505 + }, + "MN": { + "iterations": 6, + "kish_ess_after": 130.04301958269207, + "kish_ess_before": 151.41085939244604, + "max_abs_relative_error": 9.46919897805484e-11, + "state_population_change": 0.0016499138221062193, + "weight_ratio_max": 3.474149974351805, + "weight_ratio_min": 0.35335188126266914, + "weight_ratio_p01": 0.49523776104230216, + "weight_ratio_p50": 0.9208318412149251, + "weight_ratio_p99": 3.4265871491451096 + }, + "MO": { + "iterations": 6, + "kish_ess_after": 150.28855995976076, + "kish_ess_before": 158.23194083624088, + "max_abs_relative_error": 3.084701447119514e-11, + "state_population_change": 0.00042828181921650277, + "weight_ratio_max": 10.857321371887416, + "weight_ratio_min": 0.3659306948051277, + "weight_ratio_p01": 0.5328810522207296, + "weight_ratio_p50": 0.9374476160215409, + "weight_ratio_p99": 3.344175004997668 + }, + "MS": { + "iterations": 6, + "kish_ess_after": 194.35993720323629, + "kish_ess_before": 217.18543432971407, + "max_abs_relative_error": 3.6174028205860345e-12, + "state_population_change": 0.0006841429885044992, + "weight_ratio_max": 4.338111568216666, + "weight_ratio_min": 0.3856181321447649, + "weight_ratio_p01": 0.5485814598433616, + "weight_ratio_p50": 1.0465745257196808, + "weight_ratio_p99": 2.4275136697098896 + }, + "MT": { + "iterations": 7, + "kish_ess_after": 168.52718391878525, + "kish_ess_before": 189.76250275414372, + "max_abs_relative_error": 3.064851564525453e-16, + "state_population_change": 0.0017358748190534623, + "weight_ratio_max": 5.0687432009873135, + "weight_ratio_min": 0.4387433678889664, + "weight_ratio_p01": 0.5480010430329126, + "weight_ratio_p50": 0.8925699574841548, + "weight_ratio_p99": 2.9507575431717403 + }, + "NC": { + "iterations": 200, + "kish_ess_after": 275.1086971153389, + "kish_ess_before": 278.9726584586971, + "max_abs_relative_error": 1.1848246889370283e-09, + "state_population_change": 0.0014039831014873716, + "weight_ratio_max": 2.7577273646099556, + "weight_ratio_min": 0.6200495643003082, + "weight_ratio_p01": 0.7539325553217732, + "weight_ratio_p50": 0.9823821851964706, + "weight_ratio_p99": 1.6864690988771747 + }, + "ND": { + "iterations": 6, + "kish_ess_after": 130.05536811059443, + "kish_ess_before": 154.69431792442464, + "max_abs_relative_error": 1.7295935508313744e-14, + "state_population_change": 0.01321568513841287, + "weight_ratio_max": 5.014391744421486, + "weight_ratio_min": 0.1761226057569539, + "weight_ratio_p01": 0.4780602860707284, + "weight_ratio_p50": 0.9092205103528221, + "weight_ratio_p99": 4.352193337988655 + }, + "NE": { + "iterations": 5, + "kish_ess_after": 144.050125021553, + "kish_ess_before": 145.9510960348787, + "max_abs_relative_error": 6.578882145151504e-15, + "state_population_change": 0.002459740493146567, + "weight_ratio_max": 1.422471100792332, + "weight_ratio_min": 0.6904799231584663, + "weight_ratio_p01": 0.738575578083039, + "weight_ratio_p50": 0.9985622839339676, + "weight_ratio_p99": 1.2608359221138234 + }, + "NH": { + "iterations": 7, + "kish_ess_after": 134.84224735820297, + "kish_ess_before": 140.868912806551, + "max_abs_relative_error": 2.8776355530793276e-16, + "state_population_change": -0.0006008964262953498, + "weight_ratio_max": 7.201700203681179, + "weight_ratio_min": 0.3664464645233031, + "weight_ratio_p01": 0.6314592260792691, + "weight_ratio_p50": 0.9402476229509927, + "weight_ratio_p99": 2.75185502632625 + }, + "NJ": { + "iterations": 6, + "kish_ess_after": 195.70150847519798, + "kish_ess_before": 214.92794357369306, + "max_abs_relative_error": 7.615463850922807e-14, + "state_population_change": 0.0005131587266287152, + "weight_ratio_max": 20.962337419871197, + "weight_ratio_min": 0.44879034178236743, + "weight_ratio_p01": 0.5456625195749571, + "weight_ratio_p50": 0.9322207463246106, + "weight_ratio_p99": 3.5228866359615294 + }, + "NM": { + "iterations": 5, + "kish_ess_after": 187.16137837632579, + "kish_ess_before": 197.21158124194926, + "max_abs_relative_error": 1.4120361674684312e-12, + "state_population_change": 0.0037489823220291374, + "weight_ratio_max": 2.4638970888033014, + "weight_ratio_min": 0.6799336531094594, + "weight_ratio_p01": 0.7309568600135847, + "weight_ratio_p50": 0.9391259534531119, + "weight_ratio_p99": 1.5696805690341271 + }, + "NV": { + "iterations": 7, + "kish_ess_after": 137.75043418974877, + "kish_ess_before": 153.2144587425425, + "max_abs_relative_error": 7.664000180281453e-11, + "state_population_change": -6.747807648310733e-05, + "weight_ratio_max": 2.345505791753834, + "weight_ratio_min": 0.4952367155070312, + "weight_ratio_p01": 0.5814333820126326, + "weight_ratio_p50": 0.964874443918662, + "weight_ratio_p99": 1.8992623432647293 + }, + "NY": { + "iterations": 6, + "kish_ess_after": 394.4950082809546, + "kish_ess_before": 431.19504540166105, + "max_abs_relative_error": 7.67947072752309e-13, + "state_population_change": 0.0010293908193659274, + "weight_ratio_max": 4.3656663544958665, + "weight_ratio_min": 0.40889996216489577, + "weight_ratio_p01": 0.610386620427942, + "weight_ratio_p50": 0.9300849041777716, + "weight_ratio_p99": 2.34514963146062 + }, + "OH": { + "iterations": 5, + "kish_ess_after": 250.8501777176201, + "kish_ess_before": 259.8938711628161, + "max_abs_relative_error": 8.093845567904095e-12, + "state_population_change": 0.0001956323251064429, + "weight_ratio_max": 1.4222222390125214, + "weight_ratio_min": 0.5242946607948629, + "weight_ratio_p01": 0.5474248342004205, + "weight_ratio_p50": 1.040459783338835, + "weight_ratio_p99": 1.3663516796124513 + }, + "OK": { + "iterations": 7, + "kish_ess_after": 181.16704913650378, + "kish_ess_before": 184.8895033261389, + "max_abs_relative_error": 4.383679163455125e-16, + "state_population_change": 0.00042857569828624875, + "weight_ratio_max": 3.4588247745355805, + "weight_ratio_min": 0.6115635575369777, + "weight_ratio_p01": 0.7772557505558233, + "weight_ratio_p50": 0.9727316161801216, + "weight_ratio_p99": 3.1177751064861923 + }, + "OR": { + "iterations": 7, + "kish_ess_after": 162.97753656249972, + "kish_ess_before": 174.20405252731825, + "max_abs_relative_error": 6.657963373263549e-16, + "state_population_change": 0.0013419391806657188, + "weight_ratio_max": 29.17850021913966, + "weight_ratio_min": 0.44539030122745504, + "weight_ratio_p01": 0.6480314608469024, + "weight_ratio_p50": 0.9692516928969468, + "weight_ratio_p99": 5.186380608617817 + }, + "PA": { + "iterations": 7, + "kish_ess_after": 300.4167157319666, + "kish_ess_before": 313.9407214900252, + "max_abs_relative_error": 6.534415944330307e-11, + "state_population_change": -3.2037909957094435e-05, + "weight_ratio_max": 3.484734861221103, + "weight_ratio_min": 0.6673782285791794, + "weight_ratio_p01": 0.7813494899757503, + "weight_ratio_p50": 0.948023759215202, + "weight_ratio_p99": 1.8690351159609042 + }, + "RI": { + "iterations": 6, + "kish_ess_after": 110.76791529037581, + "kish_ess_before": 115.36121502541874, + "max_abs_relative_error": 4.563230915620142e-16, + "state_population_change": 0.0009673954150151154, + "weight_ratio_max": 5.842711519558639, + "weight_ratio_min": 0.2613639707268777, + "weight_ratio_p01": 0.40684789887340306, + "weight_ratio_p50": 0.9902430716292577, + "weight_ratio_p99": 2.0117717176816616 + }, + "SC": { + "iterations": 6, + "kish_ess_after": 178.81396626198685, + "kish_ess_before": 198.57355826188999, + "max_abs_relative_error": 6.221234748661518e-16, + "state_population_change": 0.00037432730104636214, + "weight_ratio_max": 2.540004594419374, + "weight_ratio_min": 0.40567877179460676, + "weight_ratio_p01": 0.5607759677746763, + "weight_ratio_p50": 0.9641424560398029, + "weight_ratio_p99": 1.9023526201063097 + }, + "SD": { + "iterations": 6, + "kish_ess_after": 126.06517075482847, + "kish_ess_before": 140.02483771729896, + "max_abs_relative_error": 3.886665856123361e-14, + "state_population_change": 0.005853617453803306, + "weight_ratio_max": 4.219623854947454, + "weight_ratio_min": 0.290768079562418, + "weight_ratio_p01": 0.4388988929250618, + "weight_ratio_p50": 0.991348607001532, + "weight_ratio_p99": 1.989161846698407 + }, + "TN": { + "iterations": 7, + "kish_ess_after": 187.72007465235436, + "kish_ess_before": 213.4611164306311, + "max_abs_relative_error": 1.2976469918613151e-11, + "state_population_change": -0.0001395796977777808, + "weight_ratio_max": 36.167419635115365, + "weight_ratio_min": 0.2125134471436896, + "weight_ratio_p01": 0.4753993712576985, + "weight_ratio_p50": 0.9457864824463943, + "weight_ratio_p99": 5.438985641894158 + }, + "TX": { + "iterations": 7, + "kish_ess_after": 622.875283326869, + "kish_ess_before": 671.2372643331317, + "max_abs_relative_error": 2.5208408461281843e-15, + "state_population_change": 0.0007271362080774058, + "weight_ratio_max": 2.441489154334037, + "weight_ratio_min": 0.2562528359264575, + "weight_ratio_p01": 0.4144655366970442, + "weight_ratio_p50": 0.9774612489864509, + "weight_ratio_p99": 1.6795583139456922 + }, + "UT": { + "iterations": 13, + "kish_ess_after": 171.5101107017762, + "kish_ess_before": 182.57153743556984, + "max_abs_relative_error": 1.7221208378450158e-16, + "state_population_change": 0.0004643673298783124, + "weight_ratio_max": 17.953997000200328, + "weight_ratio_min": 0.4889272192481173, + "weight_ratio_p01": 0.6521083129738193, + "weight_ratio_p50": 0.9226675426959777, + "weight_ratio_p99": 2.826605942358923 + }, + "VA": { + "iterations": 5, + "kish_ess_after": 204.67490777428563, + "kish_ess_before": 215.49254181633236, + "max_abs_relative_error": 2.3111203011913344e-11, + "state_population_change": 9.46913055543952e-05, + "weight_ratio_max": 1.7904017851934086, + "weight_ratio_min": 0.2749987380180666, + "weight_ratio_p01": 0.620600257328083, + "weight_ratio_p50": 1.0447298646731227, + "weight_ratio_p99": 1.4875635569315766 + }, + "VT": { + "iterations": 200, + "kish_ess_after": 144.27649161279183, + "kish_ess_before": 155.57089695495154, + "max_abs_relative_error": 2.02099815820174e-09, + "state_population_change": 0.0034734853234037466, + "weight_ratio_max": 2.5753392743213137, + "weight_ratio_min": 0.45867811208245896, + "weight_ratio_p01": 0.6335219139525595, + "weight_ratio_p50": 0.930585861497564, + "weight_ratio_p99": 1.8533349583160308 + }, + "WA": { + "iterations": 6, + "kish_ess_after": 213.1905905957163, + "kish_ess_before": 217.79313599494608, + "max_abs_relative_error": 4.970038405012709e-16, + "state_population_change": 0.0008410003103260788, + "weight_ratio_max": 2.2834693385046467, + "weight_ratio_min": 0.41388995561768055, + "weight_ratio_p01": 0.5733017909047458, + "weight_ratio_p50": 0.9801976718885493, + "weight_ratio_p99": 1.8608949652311206 + }, + "WI": { + "iterations": 7, + "kish_ess_after": 150.64327439151154, + "kish_ess_before": 168.63884922048263, + "max_abs_relative_error": 1.2483413595579352e-15, + "state_population_change": 0.002959445378266423, + "weight_ratio_max": 6.999906942589538, + "weight_ratio_min": 0.4011381734330613, + "weight_ratio_p01": 0.48998018092779766, + "weight_ratio_p50": 0.991962357739794, + "weight_ratio_p99": 4.706225719697843 + }, + "WV": { + "iterations": 5, + "kish_ess_after": 212.16376551338405, + "kish_ess_before": 220.39920666393735, + "max_abs_relative_error": 2.7928908700030374e-11, + "state_population_change": 0.0019569809223516366, + "weight_ratio_max": 1.884271722640284, + "weight_ratio_min": 0.593558926613896, + "weight_ratio_p01": 0.6624548775286552, + "weight_ratio_p50": 0.9584844874502951, + "weight_ratio_p99": 1.4228253755687024 + }, + "WY": { + "iterations": 7, + "kish_ess_after": 153.26749367012448, + "kish_ess_before": 157.0853280537897, + "max_abs_relative_error": 2.316592253090234e-12, + "state_population_change": 0.006929381573511417, + "weight_ratio_max": 5.8556154040569455, + "weight_ratio_min": 0.6421589761397712, + "weight_ratio_p01": 0.6925312327292292, + "weight_ratio_p50": 0.9267965814204009, + "weight_ratio_p99": 1.7585553227226374 + } + }, + "description": "Per-state minimum-KL reweighting of the release's household weights to the seven 25+ cells, holding the state's population under 25 fixed. Not the release solve, which fits every target jointly; it shows what binding these cells alone asks of the weights.", + "kish_ess_ratio_min": 0.8262154755509149, + "max_abs_relative_error_after": 2.0209980355900825e-09, + "weight_ratio_max": 130.9713001422298, + "weight_ratio_min": 0.1761226057569539, + "weight_ratio_p01_min": 0.3804299124992997, + "weight_ratio_p99_max": 5.9437218808502275 + }, + "state_25_plus_level_gap": { + "by_state": { + "AK": 0.0009844569750436793, + "AL": 0.0016700033215597543, + "AR": 0.0001747669458549428, + "AZ": 0.0013385209369525253, + "CA": 0.0006835535092943879, + "CO": 0.002625698191123904, + "CT": 0.0019822795205151067, + "DC": 0.03943270733219828, + "DE": -0.0013440567166137507, + "FL": 0.0002330360132432041, + "GA": 0.0021408708531109877, + "HI": 0.0011878191861411924, + "IA": 0.0035991282452041418, + "ID": 0.0012259219504462404, + "IL": 0.0013887250323312283, + "IN": 0.0040399175427197065, + "KS": 0.007890676512903427, + "KY": 0.001000626871842103, + "LA": 0.0024882095398039983, + "MA": 0.0014702468795797508, + "MD": 0.0021428898002324726, + "ME": 0.004793225108211452, + "MI": 0.0013749207282127696, + "MN": 0.0024039341759012345, + "MO": 0.0006218646383786552, + "MS": 0.0010161234067880276, + "MT": 0.0024614767684596472, + "NC": 0.0020313785702481546, + "ND": 0.020222306886470198, + "NE": 0.003737499809097544, + "NH": -0.0008144079756225997, + "NJ": 0.000733003698069945, + "NM": 0.005403996319238491, + "NV": -9.515581498009684e-05, + "NY": 0.0014507984657519124, + "OH": 0.00028176236160915025, + "OK": 0.0006442120423384434, + "OR": 0.001862196781589942, + "PA": -4.5239123472762266e-05, + "RI": 0.0013513282158670314, + "SC": 0.0005359703575440466, + "SD": 0.008764714052916567, + "TN": -0.0002018747046963476, + "TX": 0.0011070401958226395, + "UT": 0.0007561646310776382, + "VA": 0.00013651347783882883, + "VT": 0.004772367754130258, + "WA": 0.001189417306429963, + "WI": 0.004245904883424911, + "WV": 0.0027379400955021005, + "WY": 0.010057307052179887 + }, + "description": "S1501 25+ total / release 25+ weighted population - 1", + "max_abs": 0.03943270733219828, + "median_abs": 0.0013887250323312283 + } +} diff --git a/packages/microcosm-build/src/microcosm/build/us/fiscal_target_references.json b/packages/microcosm-build/src/microcosm/build/us/fiscal_target_references.json index aa8eb8b59d..b8452390ee 100644 --- a/packages/microcosm-build/src/microcosm/build/us/fiscal_target_references.json +++ b/packages/microcosm-build/src/microcosm/build/us/fiscal_target_references.json @@ -101,7 +101,8 @@ "ledger_layout_record_set_id", "age_lower_bound", "age_upper_bound", - "age_group" + "age_group", + "educational_attainment_category" ] } } diff --git a/packages/microcosm-build/src/microcosm/build/us_runtime/educational_attainment.py b/packages/microcosm-build/src/microcosm/build/us_runtime/educational_attainment.py new file mode 100644 index 0000000000..76192a5b51 --- /dev/null +++ b/packages/microcosm-build/src/microcosm/build/us_runtime/educational_attainment.py @@ -0,0 +1,705 @@ +"""Educational attainment as an auxiliary person column (microcosm#297). + +The student debt pilot's state degree-ROI work (PolicyEngine/us-student- +debt#1, Project 2) reruns PolicyEngine with counterfactual earnings for each +degree holder, so it needs every person's highest completed level next to the +engine outputs for that person. policyengine-us has no attainment input, and +none is needed: the column is *auxiliary*. Microcosm carries it for +conditioning (imputation predictors) and calibration (ACS S1501 state +margins), and no rule consumes it. The stored-input register says so +(:data:`microcosm.data.stored_inputs.US_AUXILIARY_STORED_COLUMNS`), and the +analysis joins it on ``person_id``. + +**Classes.** Seven, the population-25-and-over partition of ACS subject table +S1501 (Educational Attainment), whose Chronicle value ids they reuse, plus +``not_in_universe`` for people under 15: + +====================================== ================== =================== +Class CPS ASEC ``A_HGA`` ACS PUMS ``SCHL`` +====================================== ================== =================== +``less_than_9th_grade`` 31-34 01-11 +``9th_to_12th_grade_no_diploma`` 35-38 12-15 +``high_school_graduate_includes_ 39 16, 17 +equivalency`` +``some_college_no_degree`` 40 18, 19 +``associates_degree`` 41, 42 20 +``bachelors_degree`` 43 21 +``graduate_or_professional_degree`` 44, 45, 46 22, 23, 24 +``not_in_universe`` 0 ("Children") blank (under 3), or + any person under 15 +====================================== ================== =================== + +Collapsing the first two gives the six classes microcosm#297 asks for (less +than high school; high school diploma or GED; some college, no degree; +associate's, occupational and academic together; bachelor's; graduate or +professional): :data:`US_EDUCATIONAL_ATTAINMENT_SIX_CLASSES`. The degree-ROI +analysis compares :data:`US_DEGREE_ROI_CLASSES`: a two-year degree is +``associates_degree`` and a four-year degree ``bachelors_degree``, each against +the ``high_school_graduate_includes_equivalency`` baseline. + +**Sources.** ``A_HGA`` ("Item 18h - Educational attainment", universe all +persons, 0 = Children) is read from the official ASEC public-use person +members the build already pins +(:data:`.spm_role_source.ASEC_SPM_ROLE_SOURCES`, the archives of +:data:`.education_assistance_source.ASEC_EDUCATION_ASSISTANCE_ARCHIVES`). The +codes were checked against the Census ASEC public-use data dictionaries for +survey years 2023 to 2026 (``asec_ddl_pub_full.pdf`` under +``https://www2.census.gov/programs-surveys/cps/datasets//march/``, PDF +pages 22, 23, 24 and 28); the four agree code for code. ``SCHL`` is the ACS +PUMS "Educational attainment" field, checked against +``https://www2.census.gov/programs-surveys/acs/tech_docs/pums/data_dict/PUMS_Data_Dictionary_2024.txt``. +The S1501 categories follow the table's own rows (S1501_C01_006E to 013E for +the population 25 and over; 001E to 005E for 18 to 24). + +The CPS column is filled by an exact join on (income year, ``PERIDNUM``) to +the pinned member, with the Census ``PH_SEQ`` (the frame's +``source_household_id``), ``P_SEQ``, ``A_LINENO`` and ``A_AGE`` checked equal +wherever the frame carries them, so a support clone takes its source person's +value. No value is predicted, imputed or defaulted. The ACS +``SCHL`` map is defined and tested here, but the ACS-local lane does not read +``SCHL`` from PUMS yet; ACS-spine rows are refused rather than given a value. +""" + +from __future__ import annotations + +from collections.abc import Iterable, Mapping +from pathlib import Path +from types import MappingProxyType + +import numpy as np +import pandas as pd + +from microcosm.build.gates import GateResult +from microcosm.frame import Frame +from microcosm.frame.units import US_SCHEMA + +from .education_assistance_source import fetch_asec_education_assistance_source +from .spm_role_source import ( + ASEC_SPM_ROLE_SOURCES, + AsecSpmRoleSource, + _exact_person_keys, + read_pinned_asec_person_columns, +) + +__all__ = [ + "ACS_SCHL_ATTAINMENT_CLASSES", + "ASEC_A_HGA_ATTAINMENT_CLASSES", + "ASSOCIATES_DEGREE", + "BACHELORS_DEGREE", + "GRADE_9_TO_12_NO_DIPLOMA", + "GRADUATE_OR_PROFESSIONAL_DEGREE", + "HIGH_SCHOOL_GRADUATE", + "LESS_THAN_9TH_GRADE", + "NOT_IN_UNIVERSE", + "S1501_ATTAINMENT_CATEGORY_CLASSES", + "S1501_BINDING_UNIVERSE", + "SOME_COLLEGE_NO_DEGREE", + "US_ASEC_ATTAINMENT_SOURCE_COLUMN", + "US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN", + "US_DEGREE_ROI_CLASSES", + "US_EDUCATIONAL_ATTAINMENT_CLASSES", + "US_EDUCATIONAL_ATTAINMENT_CLASSES_METADATA_KEY", + "US_EDUCATIONAL_ATTAINMENT_MINIMUM_AGE", + "US_EDUCATIONAL_ATTAINMENT_SIX_CLASSES", + "US_EDUCATIONAL_ATTAINMENT_TARGET_FAMILY", + "US_EDUCATIONAL_ATTAINMENT_TARGET_MATERIALIZER", + "US_EDUCATIONAL_ATTAINMENT_VALUES", + "EducationalAttainmentError", + "attainment_classes_from_metadata", + "attainment_from_a_hga", + "attainment_from_schl", + "attainment_target_person_indicator", + "derive_cps_educational_attainment", + "load_asec_attainment_sources", + "us_cps_educational_attainment_signal_gate", + "us_cps_educational_attainment_summary", + "with_us_cps_educational_attainment", +] + + +class EducationalAttainmentError(ValueError): + """The attainment derivation refused its inputs.""" + + +#: The auxiliary person column, named for its source (CPS ASEC ``A_HGA``). +US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN = "cps_educational_attainment" +#: The raw Census code, carried beside the class (uppercase Census fields pass +#: the stored-input rule by convention; see microcosm.data.stored_inputs). +US_ASEC_ATTAINMENT_SOURCE_COLUMN = "A_HGA" +#: CPS ASEC asks attainment of persons 15 and over; ``A_HGA`` is 0 +#: ("Children") below that. The ACS asks from age 3; the column puts every +#: person under 15 out of universe so both sources share one universe. +US_EDUCATIONAL_ATTAINMENT_MINIMUM_AGE = 15 + +LESS_THAN_9TH_GRADE = "less_than_9th_grade" +GRADE_9_TO_12_NO_DIPLOMA = "9th_to_12th_grade_no_diploma" +HIGH_SCHOOL_GRADUATE = "high_school_graduate_includes_equivalency" +SOME_COLLEGE_NO_DEGREE = "some_college_no_degree" +ASSOCIATES_DEGREE = "associates_degree" +BACHELORS_DEGREE = "bachelors_degree" +GRADUATE_OR_PROFESSIONAL_DEGREE = "graduate_or_professional_degree" +NOT_IN_UNIVERSE = "not_in_universe" + +#: The seven classes, lowest to highest: S1501's population-25-and-over rows. +US_EDUCATIONAL_ATTAINMENT_CLASSES: tuple[str, ...] = ( + LESS_THAN_9TH_GRADE, + GRADE_9_TO_12_NO_DIPLOMA, + HIGH_SCHOOL_GRADUATE, + SOME_COLLEGE_NO_DEGREE, + ASSOCIATES_DEGREE, + BACHELORS_DEGREE, + GRADUATE_OR_PROFESSIONAL_DEGREE, +) +#: Every value the column may hold. +US_EDUCATIONAL_ATTAINMENT_VALUES: tuple[str, ...] = ( + *US_EDUCATIONAL_ATTAINMENT_CLASSES, + NOT_IN_UNIVERSE, +) + +#: Class -> the six classes microcosm#297 asks for (the two below-diploma +#: classes merge into ``less_than_high_school``). +US_EDUCATIONAL_ATTAINMENT_SIX_CLASSES: Mapping[str, str] = MappingProxyType( + { + LESS_THAN_9TH_GRADE: "less_than_high_school", + GRADE_9_TO_12_NO_DIPLOMA: "less_than_high_school", + HIGH_SCHOOL_GRADUATE: HIGH_SCHOOL_GRADUATE, + SOME_COLLEGE_NO_DEGREE: SOME_COLLEGE_NO_DEGREE, + ASSOCIATES_DEGREE: ASSOCIATES_DEGREE, + BACHELORS_DEGREE: BACHELORS_DEGREE, + GRADUATE_OR_PROFESSIONAL_DEGREE: GRADUATE_OR_PROFESSIONAL_DEGREE, + NOT_IN_UNIVERSE: NOT_IN_UNIVERSE, + } +) + +#: The classes the state degree-ROI analysis (us-student-debt#5) compares. +US_DEGREE_ROI_CLASSES: Mapping[str, str] = MappingProxyType( + { + "baseline": HIGH_SCHOOL_GRADUATE, + "two_year_degree": ASSOCIATES_DEGREE, + "four_year_degree": BACHELORS_DEGREE, + } +) + + +def _codes(classes: Mapping[str, Iterable[int]]) -> Mapping[int, str]: + mapped: dict[int, str] = {} + for label, codes in classes.items(): + for code in codes: + if code in mapped: + raise AssertionError(f"code {code} mapped twice") + mapped[int(code)] = label + return MappingProxyType(dict(sorted(mapped.items()))) + + +#: ASEC ``A_HGA`` code -> class. The Census dictionaries list exactly these +#: codes (0 and 31 to 46) for survey years 2023 to 2026. +ASEC_A_HGA_ATTAINMENT_CLASSES: Mapping[int, str] = _codes( + { + NOT_IN_UNIVERSE: (0,), + # 31 less than 1st grade; 32 1st-4th; 33 5th-6th; 34 7th and 8th. + LESS_THAN_9TH_GRADE: range(31, 35), + # 35 9th; 36 10th; 37 11th; 38 12th grade no diploma. + GRADE_9_TO_12_NO_DIPLOMA: range(35, 39), + # 39 high school graduate - high school diploma or equivalent. + HIGH_SCHOOL_GRADUATE: (39,), + # 40 some college but no degree. + SOME_COLLEGE_NO_DEGREE: (40,), + # 41 associate degree, occupation/vocation program; 42 academic program. + ASSOCIATES_DEGREE: (41, 42), + # 43 bachelor's degree. + BACHELORS_DEGREE: (43,), + # 44 master's; 45 professional school degree; 46 doctorate. + GRADUATE_OR_PROFESSIONAL_DEGREE: (44, 45, 46), + } +) + +#: ACS PUMS ``SCHL`` code -> class (2024 PUMS data dictionary). Blank is +#: "N/A (less than 3 years old)". +ACS_SCHL_ATTAINMENT_CLASSES: Mapping[int, str] = _codes( + { + # 01 no schooling; 02 nursery; 03 kindergarten; 04-11 grades 1 to 8. + LESS_THAN_9TH_GRADE: range(1, 12), + # 12-14 grades 9 to 11; 15 12th grade, no diploma. + GRADE_9_TO_12_NO_DIPLOMA: range(12, 16), + # 16 regular high school diploma; 17 GED or alternative credential. + HIGH_SCHOOL_GRADUATE: (16, 17), + # 18 some college, less than 1 year; 19 1+ years of credit, no degree. + SOME_COLLEGE_NO_DEGREE: (18, 19), + # 20 associate's degree. + ASSOCIATES_DEGREE: (20,), + # 21 bachelor's degree. + BACHELORS_DEGREE: (21,), + # 22 master's; 23 professional degree beyond a bachelor's; 24 doctorate. + GRADUATE_OR_PROFESSIONAL_DEGREE: (22, 23, 24), + } +) + +#: S1501 category (the Chronicle ``educational_attainment`` value id of +#: ``packages/census/acs_s1501_state_2024``) -> the classes it counts. The +#: population-25-and-over rows are one class each; the 18-to-24 rows merge +#: neighbouring classes. +S1501_ATTAINMENT_CATEGORY_CLASSES: Mapping[str, frozenset[str]] = MappingProxyType( + { + **{label: frozenset({label}) for label in US_EDUCATIONAL_ATTAINMENT_CLASSES}, + "less_than_high_school_graduate": frozenset( + {LESS_THAN_9TH_GRADE, GRADE_9_TO_12_NO_DIPLOMA} + ), + "some_college_or_associates_degree": frozenset( + {SOME_COLLEGE_NO_DEGREE, ASSOCIATES_DEGREE} + ), + "bachelors_degree_or_higher": frozenset( + {BACHELORS_DEGREE, GRADUATE_OR_PROFESSIONAL_DEGREE} + ), + } +) +#: The S1501 universe that binds: the population 25 and over. The 18-to-24 +#: universe is held out (see +#: :func:`microcosm.build.us_runtime.fiscal_targets._acs_attainment_reference_from_fact`). +S1501_BINDING_UNIVERSE = "25_plus" + +#: Target metadata naming the materializer, family and class set. +US_EDUCATIONAL_ATTAINMENT_TARGET_MATERIALIZER = "population_attainment" +US_EDUCATIONAL_ATTAINMENT_TARGET_FAMILY = "census_educational_attainment" +US_EDUCATIONAL_ATTAINMENT_CLASSES_METADATA_KEY = "educational_attainment_classes" + +_JOIN_KEY = "PERIDNUM" +_SOURCE_YEAR = "source_year" +_IDENTITY_COLUMNS = ("PH_SEQ", "P_SEQ", "A_LINENO", "A_AGE") +_MEMBER_COLUMNS = (_JOIN_KEY, *_IDENTITY_COLUMNS, US_ASEC_ATTAINMENT_SOURCE_COLUMN) +_EXAMPLES = 5 +#: Weighted shares of the population 25 and over the gate requires. ACS 2024 +#: S1501 nationally: about 10% below a diploma, 37% bachelor's or higher. +_LESS_THAN_HIGH_SCHOOL_SHARE_BAND = (0.05, 0.16) +_BACHELORS_OR_HIGHER_SHARE_BAND = (0.25, 0.45) + + +def _refuse(message: str) -> None: + raise EducationalAttainmentError(message) + + +def _integer_codes(values: object, *, label: str) -> np.ndarray: + series = pd.Series(values) + numeric = pd.to_numeric(series, errors="coerce").to_numpy(dtype=np.float64) + bad = ~np.isfinite(numeric) | (numeric != np.floor(numeric)) + if bad.any(): + _refuse( + f"{label} has {int(bad.sum())} missing or non-integer codes, e.g. " + f"{series[bad].head(_EXAMPLES).tolist()}." + ) + return numeric.astype(np.int64) + + +def _classify(codes: np.ndarray, mapping: Mapping[int, str], label: str) -> np.ndarray: + known = np.isin(codes, np.fromiter(mapping, dtype=np.int64)) + if not known.all(): + _refuse( + f"{label} has {int((~known).sum())} codes outside the reviewed Census " + f"codes {sorted(mapping)}, e.g. {sorted(set(codes[~known].tolist()))[:_EXAMPLES]}." + ) + lookup = pd.Series(mapping) + return lookup.reindex(codes).to_numpy(dtype=object) + + +def attainment_from_a_hga(codes: object) -> np.ndarray: + """Map CPS ASEC ``A_HGA`` codes to classes, refusing any other code.""" + + return _classify( + _integer_codes(codes, label="A_HGA"), ASEC_A_HGA_ATTAINMENT_CLASSES, "A_HGA" + ) + + +def attainment_from_schl(codes: object, ages: object) -> np.ndarray: + """Map ACS PUMS ``SCHL`` codes to classes for persons of ``ages``. + + ``SCHL`` is blank only for persons under 3, and every person under + :data:`US_EDUCATIONAL_ATTAINMENT_MINIMUM_AGE` is ``not_in_universe`` so + the ACS column shares the CPS universe. + """ + + age = _integer_codes(ages, label="age") + series = pd.Series(codes).reset_index(drop=True) + blank = series.isna() | series.astype(str).str.strip().eq("") + if (blank & pd.Series(age >= 3)).any(): + _refuse("SCHL is blank for a person aged 3 or over.") + result = np.full(len(series), NOT_IN_UNIVERSE, dtype=object) + answered = ~blank.to_numpy() + if answered.any(): + result[answered] = _classify( + _integer_codes(series[answered], label="SCHL"), + ACS_SCHL_ATTAINMENT_CLASSES, + "SCHL", + ) + result[age < US_EDUCATIONAL_ATTAINMENT_MINIMUM_AGE] = NOT_IN_UNIVERSE + return result + + +def _load_one_member( + path: Path, pin: AsecSpmRoleSource +) -> tuple[pd.DataFrame, dict[str, object]]: + label = f"ASEC {pin.survey_year} Census person member {pin.member}" + try: + source, form = read_pinned_asec_person_columns( + path, pin, label, _MEMBER_COLUMNS + ) + except ValueError as error: + raise EducationalAttainmentError(str(error)) from error + if len(source) != pin.persons: + _refuse(f"{label} holds {len(source)} persons; the pin records {pin.persons}.") + try: + source[_JOIN_KEY] = _exact_person_keys(source[_JOIN_KEY], label) + except ValueError as error: + raise EducationalAttainmentError(str(error)) from error + if source[_JOIN_KEY].duplicated().any(): + _refuse(f"{label} repeats PERIDNUM; the join must be many-to-one.") + for column in (*_IDENTITY_COLUMNS, US_ASEC_ATTAINMENT_SOURCE_COLUMN): + source[column] = _integer_codes(source[column], label=f"{label} {column}") + codes = source[US_ASEC_ATTAINMENT_SOURCE_COLUMN].to_numpy() + attainment_from_a_hga(codes) + child = source["A_AGE"].to_numpy() < US_EDUCATIONAL_ATTAINMENT_MINIMUM_AGE + zero = codes == 0 + if (zero != child).any(): + _refuse( + f"{label}: A_HGA is 0 ('Children') for {int((zero & ~child).sum())} " + f"persons aged 15+ and nonzero for {int((child & ~zero).sum())} under " + "15; the reviewed universe is persons 15 and over." + ) + counts = pd.Series(codes).value_counts() + return source, { + "income_year": pin.income_year, + "survey_year": pin.survey_year, + "source_form": form, + "official_archive_url": pin.official_archive_url, + "archive_sha256": pin.archive_sha256, + "member": pin.member, + "member_sha256": pin.csv_sha256, + "persons": len(source), + "a_hga_counts": { + str(code): int(counts.get(code, 0)) + for code in ASEC_A_HGA_ATTAINMENT_CLASSES + }, + } + + +def load_asec_attainment_sources( + income_years: Iterable[int], + paths: Mapping[int, str | Path] | None = None, + *, + pins: Mapping[int, AsecSpmRoleSource] | None = None, +) -> pd.DataFrame: + """Read ``A_HGA`` and the identity columns from each pinned person member. + + ``paths`` maps income years to the official archive or its extracted + person CSV; an income year without a path is fetched from the Census + archive and verified (:func:`.education_assistance_source. + fetch_asec_education_assistance_source`). ``pins`` defaults to + :data:`.spm_role_source.ASEC_SPM_ROLE_SOURCES`; an explicit mapping is for + synthetic tests. The result carries ``source_year`` and one row per + member person; its ``attrs["provenance"]`` records every member read. + """ + + pins = ASEC_SPM_ROLE_SOURCES if pins is None else pins + years = sorted({int(year) for year in income_years}) + if not years: + _refuse("No income years to read A_HGA for.") + parts: list[pd.DataFrame] = [] + provenance: dict[str, object] = {} + for year in years: + pin = pins.get(year) + if pin is None: + _refuse( + f"No pinned Census ASEC person member covers income year {year}; " + f"pinned income years: {sorted(pins)}." + ) + if pin.income_year != year: + _refuse(f"Census ASEC pin for {year} is for income year {pin.income_year}.") + provided = None if paths is None else paths.get(year) + path = ( + Path(provided).expanduser() + if provided is not None + else fetch_asec_education_assistance_source(year) + ) + source, record = _load_one_member(path, pin) + source.insert(0, _SOURCE_YEAR, np.int64(year)) + parts.append(source) + provenance[str(year)] = record + result = pd.concat(parts, ignore_index=True) + result.attrs["provenance"] = provenance + return result + + +def derive_cps_educational_attainment( + person: pd.DataFrame, + sources: pd.DataFrame, +) -> tuple[np.ndarray, np.ndarray, dict[str, object]]: + """``A_HGA`` and the class for every person, by exact Census identity. + + ``person`` is a US person table carrying ``source_year`` (the ASEC income + year) and ``PERIDNUM``; ``sources`` is + :func:`load_asec_attainment_sources`' result. Each person takes the member + row of its own income year and ``PERIDNUM``, so a support clone takes its + source person's value. The member's ``PH_SEQ`` must equal + ``source_household_id`` (or, on an unpooled table without it, ``PH_SEQ``), + and ``P_SEQ``, ``A_LINENO`` and ``A_AGE`` must agree wherever the table + carries them. + Refuses a person with no ``PERIDNUM`` (an ACS-spine row), an income year + the sources do not cover, or a key the member lacks. + """ + + for column in (_SOURCE_YEAR, _JOIN_KEY): + if column not in person.columns: + _refuse(f"Person table lacks {column!r}; attainment joins on it.") + if person[_JOIN_KEY].isna().any(): + _refuse( + f"{int(person[_JOIN_KEY].isna().sum())} persons have no PERIDNUM. " + "ACS-spine rows need the SCHL lane (attainment_from_schl), which " + "the ACS-local build does not read yet." + ) + years = _integer_codes(person[_SOURCE_YEAR], label="person source_year") + try: + keys = _exact_person_keys(person[_JOIN_KEY].reset_index(drop=True), "person") + except ValueError as error: + raise EducationalAttainmentError(str(error)) from error + source_years = _integer_codes(sources[_SOURCE_YEAR], label="source source_year") + uncovered = sorted(set(years.tolist()) - set(source_years.tolist())) + if uncovered: + _refuse(f"Attainment sources do not cover income year(s) {uncovered}.") + + a_hga = np.zeros(len(person), dtype=np.int64) + identity_checked: dict[str, int] = {} + joined: dict[str, int] = {} + for year in sorted(set(years.tolist())): + mask = years == year + member = sources.loc[source_years == year].set_index(_JOIN_KEY) + year_keys = keys[mask] + missing = ~year_keys.isin(member.index) + if missing.any(): + _refuse( + f"{int(missing.sum())} income-year {year} persons have no row in " + f"the Census member, e.g. PERIDNUM " + f"{year_keys[missing].head(_EXAMPLES).tolist()}." + ) + aligned = member.reindex(year_keys.to_numpy()) + for member_column in _IDENTITY_COLUMNS: + frame_column = member_column + if member_column == "PH_SEQ" and "source_household_id" in person.columns: + # Pooling globalizes the frame's PH_SEQ; the raw Census PH_SEQ + # survives as source_household_id (as the ED_VAL fill reads it). + frame_column = "source_household_id" + if frame_column not in person.columns: + continue + observed = pd.to_numeric( + person.loc[mask, frame_column], errors="coerce" + ).to_numpy(dtype=np.float64) + expected = aligned[member_column].to_numpy(dtype=np.float64) + disagree = ~np.isfinite(observed) | (observed != expected) + if disagree.any(): + _refuse( + f"Person {frame_column} disagrees with the income-year {year} " + f"Census member {member_column} on {int(disagree.sum())} " + f"PERIDNUM-joined rows, e.g. PERIDNUM " + f"{year_keys[disagree].head(_EXAMPLES).tolist()}." + ) + identity_checked[frame_column] = identity_checked.get( + frame_column, 0 + ) + int(mask.sum()) + a_hga[mask] = aligned[US_ASEC_ATTAINMENT_SOURCE_COLUMN].to_numpy(dtype=np.int64) + joined[str(year)] = int(mask.sum()) + + classes = attainment_from_a_hga(a_hga) + counts = pd.Series(classes).value_counts() + return ( + a_hga, + classes, + { + "operation": "exact_source_join", + "join_key": "(source_year, PERIDNUM); many persons to one member row", + "column": US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN, + "column_role": "auxiliary", + "source_column": US_ASEC_ATTAINMENT_SOURCE_COLUMN, + "joined_persons_by_income_year": joined, + "identity_columns_verified": identity_checked, + "class_rows": { + label: int(counts.get(label, 0)) + for label in US_EDUCATIONAL_ATTAINMENT_VALUES + }, + "sources": sources.attrs.get("provenance", {}), + }, + ) + + +def with_us_cps_educational_attainment( + frame: Frame, + *, + sources: pd.DataFrame, +) -> tuple[Frame, dict[str, object]]: + """Append ``A_HGA`` and :data:`US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN`. + + A column the person table already carries is never overwritten: it must + equal the derivation, which then leaves it as it is. Returns the frame + and the derivation's provenance record. + """ + + if frame.schema != US_SCHEMA: + _refuse("US educational attainment requires the US schema.") + person = frame.table("person") + a_hga, classes, record = derive_cps_educational_attainment(person, sources) + tables = {entity: frame.table(entity).copy() for entity in frame.entities} + out = tables["person"] + for column, values in ( + (US_ASEC_ATTAINMENT_SOURCE_COLUMN, a_hga), + (US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN, classes), + ): + if column in out.columns: + carried = out[column].to_numpy() + if column == US_ASEC_ATTAINMENT_SOURCE_COLUMN: + carried = _integer_codes(carried, label=f"carried {column}") + if not np.array_equal(carried.astype(values.dtype), values): + _refuse( + f"The person table already carries {column} and it differs " + "from the Census derivation; it is never overwritten." + ) + record.setdefault("columns_verified_equal", []).append(column) + continue + out[column] = values + record.setdefault("columns_added", []).append(column) + result = Frame( + tables, + frame.schema, + {entity: frame.weights_for(entity) for entity in frame.weighted_entities}, + frame.strata, + mass_log=frame.mass_log, + metadata=frame.metadata, + ) + return result, record + + +def attainment_classes_from_metadata(metadata: Mapping[str, str]) -> frozenset[str]: + """The class set a compiled attainment target counts.""" + + raw = str(metadata.get(US_EDUCATIONAL_ATTAINMENT_CLASSES_METADATA_KEY, "")) + classes = frozenset(part for part in raw.split(",") if part) + unknown = sorted(classes - set(US_EDUCATIONAL_ATTAINMENT_CLASSES)) + if not classes or unknown: + _refuse( + f"Attainment target metadata names no class or unknown classes: {raw!r}." + ) + return classes + + +def _as_bound(value: object) -> float: + text = str(value) + if text == "-inf": + return -np.inf + if text == "inf": + return np.inf + return float(text) + + +def attainment_target_person_indicator( + attainment: object, + age: object, + metadata: Mapping[str, str], +) -> np.ndarray: + """1.0 for each person a compiled attainment target counts, else 0.0. + + The target's age band is half-open, ``age_lower_bound <= age < + age_upper_bound``, as every age materializer reads it; the state mask is + the caller's, on the household collapse. + """ + + classes = attainment_classes_from_metadata(metadata) + values = pd.Series(attainment).astype(object).to_numpy() + unknown = ~pd.Series(values).isin(US_EDUCATIONAL_ATTAINMENT_VALUES).to_numpy() + if unknown.any(): + _refuse( + f"{US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN} has {int(unknown.sum())} values " + "outside the reviewed classes." + ) + ages = np.asarray(age, dtype=np.float64) + lower = _as_bound(metadata.get("age_lower_bound", "-inf")) + upper = _as_bound(metadata.get("age_upper_bound", "inf")) + in_band = (ages >= lower) & (ages < upper) + in_class = pd.Series(values).isin(sorted(classes)).to_numpy() + return (in_band & in_class).astype(np.float64) + + +def us_cps_educational_attainment_summary(frame: Frame) -> dict[str, object]: + """Weighted class shares overall and for the population 25 and over.""" + + person = frame.table("person") + weights = np.asarray(frame.resolve_weights("person").values, dtype=np.float64) + classes = person[US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN].astype(object) + age = pd.to_numeric(person["age"], errors="coerce").to_numpy(dtype=np.float64) + adult = age >= 25 + total_adult = float(weights[adult].sum()) + summary: dict[str, object] = { + "persons": len(person), + "unknown_values": int((~classes.isin(US_EDUCATIONAL_ATTAINMENT_VALUES)).sum()), + "missing_values": int(classes.isna().sum()), + "weighted_population": float(weights.sum()), + "weighted_population_25_plus": total_adult, + "rows_by_class": { + label: int(classes.eq(label).sum()) + for label in US_EDUCATIONAL_ATTAINMENT_VALUES + }, + "share_25_plus_by_class": { + label: ( + float(weights[adult & classes.eq(label).to_numpy()].sum()) / total_adult + if total_adult > 0 + else 0.0 + ) + for label in US_EDUCATIONAL_ATTAINMENT_VALUES + }, + } + if "A_AGE" in person.columns: + source_age = pd.to_numeric(person["A_AGE"], errors="coerce").to_numpy() + niu = classes.eq(NOT_IN_UNIVERSE).to_numpy() + child = source_age < US_EDUCATIONAL_ATTAINMENT_MINIMUM_AGE + summary["universe_disagreements"] = int((niu != child).sum()) + shares = summary["share_25_plus_by_class"] + summary["less_than_high_school_share_25_plus"] = float( + shares[LESS_THAN_9TH_GRADE] + shares[GRADE_9_TO_12_NO_DIPLOMA] + ) + summary["bachelors_or_higher_share_25_plus"] = float( + shares[BACHELORS_DEGREE] + shares[GRADUATE_OR_PROFESSIONAL_DEGREE] + ) + summary["less_than_high_school_share_band"] = list( + _LESS_THAN_HIGH_SCHOOL_SHARE_BAND + ) + summary["bachelors_or_higher_share_band"] = list(_BACHELORS_OR_HIGHER_SHARE_BAND) + return summary + + +def us_cps_educational_attainment_signal_gate(frame: Frame) -> GateResult: + """Require a complete, in-vocabulary, plausible attainment column.""" + + person = frame.table("person") + if US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN not in person.columns: + return GateResult( + name="cps_educational_attainment_signal", + passed=False, + failures=( + f"person column {US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN} missing.", + ), + details={}, + ) + summary = us_cps_educational_attainment_summary(frame) + failures: list[str] = [] + for key in ("unknown_values", "missing_values", "universe_disagreements"): + count = int(summary.get(key, 0)) + if count: + failures.append(f"{key}: {count}.") + for share_key, band_key in ( + ("less_than_high_school_share_25_plus", "less_than_high_school_share_band"), + ("bachelors_or_higher_share_25_plus", "bachelors_or_higher_share_band"), + ): + share = float(summary[share_key]) + low, high = summary[band_key] + if not low <= share <= high: + failures.append(f"{share_key} {share:.3f} outside [{low}, {high}].") + return GateResult( + name="cps_educational_attainment_signal", + passed=not failures, + failures=tuple(failures), + details=summary, + ) diff --git a/packages/microcosm-build/src/microcosm/build/us_runtime/fiscal_targets.py b/packages/microcosm-build/src/microcosm/build/us_runtime/fiscal_targets.py index 8ad5c19839..47112cb3e3 100644 --- a/packages/microcosm-build/src/microcosm/build/us_runtime/fiscal_targets.py +++ b/packages/microcosm-build/src/microcosm/build/us_runtime/fiscal_targets.py @@ -11,6 +11,7 @@ import json import math +import re from collections.abc import Iterable, Mapping from dataclasses import dataclass, replace from functools import cache @@ -29,6 +30,15 @@ from microcosm.build.us_runtime.congressional_district_vintage import ( translate_congressional_district_facts_to_current_vintage, ) +from microcosm.build.us_runtime.educational_attainment import ( + S1501_ATTAINMENT_CATEGORY_CLASSES, + S1501_BINDING_UNIVERSE, + US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN, + US_EDUCATIONAL_ATTAINMENT_CLASSES, + US_EDUCATIONAL_ATTAINMENT_CLASSES_METADATA_KEY, + US_EDUCATIONAL_ATTAINMENT_TARGET_FAMILY, + US_EDUCATIONAL_ATTAINMENT_TARGET_MATERIALIZER, +) from microcosm.build.us_runtime.target_aging import ( age_us_dollar_targets, enforce_period_contract, @@ -3103,6 +3113,11 @@ def _reference_from_ledger_fact( if source_name == "census_stc": return _state_income_tax_reference_from_fact(fact, target_period=target_period) if source_name == "census_acs": + if _s1501_state_attainment_record_set(fact) is not None: + return _acs_attainment_reference_from_fact( + fact, + target_period=target_period, + ) if _geography_level(fact) != "congressional_district": return None return _population_age_reference_from_fact( @@ -3483,6 +3498,129 @@ def _population_age_reference_from_fact( ) +#: ACS S1501 state educational-attainment record sets +#: (``packages/census/acs_s1501_state_2024``, PolicyEngine/chronicle#310): +#: ``census_acs.acs1_.s1501.state_attainment_.``. +_S1501_STATE_ATTAINMENT_RECORD_SET = re.compile( + r"census_acs\.acs1_(?P\d{4})\.s1501\.state_attainment_" + r"(?P25_plus|18_to_24)\.(?P\d{2})" +) +#: The age band each S1501 universe must declare, as ``_age_bounds`` reads it. +_S1501_UNIVERSE_AGE_BOUNDS = {"25_plus": ("25", "inf"), "18_to_24": ("18", "25")} +US_EDUCATIONAL_ATTAINMENT_TARGET_ROLE = "population_educational_attainment" + + +def _s1501_state_attainment_record_set(fact: object) -> re.Match[str] | None: + return _S1501_STATE_ATTAINMENT_RECORD_SET.fullmatch( + _str_at(fact, "layout", "record_set_id") + ) + + +def _acs_attainment_reference_from_fact( + fact: object, + *, + target_period: int | str, +) -> LedgerTargetReference | None: + """Compile one ACS S1501 state attainment cell (microcosm#297). + + Binds the population-25-and-over detail rows, one per state and class, as + person counts of the auxiliary ``cps_educational_attainment`` column in + the cell's age band. ACS population margins are raw survey quantities, + which the fact-to-target doctrine admits (docs/us-fact-to-target.md); no + tax-benefit quantity is involved. Returns ``None``, by design, for: + + - the universe ``Total`` rows: the population level by state and age + binds from Census PEP, so a second, ACS-weighted level would only fight + it; + - the 18-to-24 universe: the ACS counts college students living in + dormitories in the state of their college (group quarters), while the + CPS counts them in their parents' household, so state cells at those + ages measure a different residence concept. The receipt reports them + held out; + - Puerto Rico and any geography outside the 50 states and DC. + + A detail row whose category, age band or measure is not the reviewed one + raises rather than drops, so a changed package cannot bind silently wrong. + """ + + match = _s1501_state_attainment_record_set(fact) + if match is None: + return None + if match["universe"] != S1501_BINDING_UNIVERSE: + return None + if _geography_level(fact) != "state": + return None + state_fips = _state_fips(fact) + if state_fips is None: + return None + source_record_id = _source_record_id(fact) + if not source_record_id: + return None + categories = [ + _str_at(row, "value") + for row in _constraint_rows(fact) + if _str_at(row, "variable") == "educational_attainment" + ] + if not categories: + return None + if len(categories) != 1 or any( + _str_at(row, "operator") != "==" + for row in _constraint_rows(fact) + if _str_at(row, "variable") == "educational_attainment" + ): + raise ValueError( + f"S1501 fact {source_record_id} declares educational_attainment " + "other than as one equality constraint." + ) + category = categories[0] + classes = S1501_ATTAINMENT_CATEGORY_CLASSES.get(category) + if classes is None: + raise ValueError( + f"S1501 fact {source_record_id} has unreviewed attainment category " + f"{category!r}; reviewed: {sorted(S1501_ATTAINMENT_CATEGORY_CLASSES)}." + ) + if _measure_id(fact) != "population": + raise ValueError( + f"S1501 fact {source_record_id} has measure {_measure_id(fact)!r}, " + "not population." + ) + lower, upper = _age_bounds(fact) + expected_bounds = _S1501_UNIVERSE_AGE_BOUNDS[match["universe"]] + if (lower, upper) != expected_bounds: + raise ValueError( + f"S1501 fact {source_record_id} declares ages [{lower}, {upper}), " + f"not the {match['universe']} universe {list(expected_bounds)}." + ) + metadata = { + "materializer": US_EDUCATIONAL_ATTAINMENT_TARGET_MATERIALIZER, + "measure_mode": "indicator_sum", + "source_measure_id": "population", + "source_period": str(_period_value(fact)), + "target_period": str(target_period), + "target_role": US_EDUCATIONAL_ATTAINMENT_TARGET_ROLE, + "geography_scope": "state", + "state_fips": state_fips, + "age_lower_bound": lower, + "age_upper_bound": upper, + AGE_BOUND_STAMP_SOURCE_KEY: _age_bound_stamp_source(fact), + "educational_attainment_category": category, + US_EDUCATIONAL_ATTAINMENT_CLASSES_METADATA_KEY: ",".join( + label for label in US_EDUCATIONAL_ATTAINMENT_CLASSES if label in classes + ), + "educational_attainment_column": US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN, + } + return LedgerTargetReference( + name=source_record_id, + ledger_source_record_id=source_record_id, + entity="household", + measure=source_record_id, + period=target_period, + family=US_EDUCATIONAL_ATTAINMENT_TARGET_FAMILY, + metadata=metadata, + hierarchy=_us_hierarchy_seed("census_acs", "educational_attainment"), + ) + + # SSA by-area record sets carry an eligibility category (total/aged/blind/ # disabled) fused into ``layout.groupby_value_id`` (``all_areas_total``, # ``alabama_aged`` …). Only the all-category ``total`` has a PolicyEngine-US diff --git a/packages/microcosm-build/tests/engine_free/us/test_us_educational_attainment.py b/packages/microcosm-build/tests/engine_free/us/test_us_educational_attainment.py new file mode 100644 index 0000000000..53e9e40e51 --- /dev/null +++ b/packages/microcosm-build/tests/engine_free/us/test_us_educational_attainment.py @@ -0,0 +1,600 @@ +"""The auxiliary CPS educational-attainment column and its S1501 targets (#297).""" + +from __future__ import annotations + +import dataclasses +import hashlib +from pathlib import Path + +import numpy as np +import pandas as pd +import pytest + +from microcosm.build.us_runtime import educational_attainment as ea +from microcosm.build.us_runtime.fiscal_targets import ( + US_EDUCATIONAL_ATTAINMENT_TARGET_ROLE, + compile_us_fiscal_target_registry, +) +from microcosm.build.us_runtime.spm_role_source import AsecSpmRoleSource +from microcosm.frame import Frame, WeightKind, Weights +from microcosm.frame.units import US_SCHEMA +from test_support.microcosm_build.us_fiscal_targets import ( + _dynamic_ledger_fact, + packaged_reference_facts, +) +from test_support.microcosm_build.us_stored_input_register import ( + _load_builder_module, +) + +# --------------------------------------------------------------------------- +# Code maps, checked against the Census dictionaries +# --------------------------------------------------------------------------- + + +def test_a_hga_map_covers_exactly_the_census_codes(): + """ASEC 2023-2026 data dictionaries, Item 18h: 0 (Children) and 31-46.""" + + assert set(ea.ASEC_A_HGA_ATTAINMENT_CLASSES) == {0, *range(31, 47)} + expected = { + ea.NOT_IN_UNIVERSE: [0], + ea.LESS_THAN_9TH_GRADE: [31, 32, 33, 34], + ea.GRADE_9_TO_12_NO_DIPLOMA: [35, 36, 37, 38], + ea.HIGH_SCHOOL_GRADUATE: [39], + ea.SOME_COLLEGE_NO_DEGREE: [40], + ea.ASSOCIATES_DEGREE: [41, 42], + ea.BACHELORS_DEGREE: [43], + ea.GRADUATE_OR_PROFESSIONAL_DEGREE: [44, 45, 46], + } + for label, codes in expected.items(): + assert [ + code + for code, mapped in ea.ASEC_A_HGA_ATTAINMENT_CLASSES.items() + if mapped == label + ] == codes + + +def test_schl_map_covers_exactly_the_pums_codes(): + """2024 ACS PUMS data dictionary, SCHL: 01-24, blank under age 3.""" + + assert set(ea.ACS_SCHL_ATTAINMENT_CLASSES) == set(range(1, 25)) + assert ea.ACS_SCHL_ATTAINMENT_CLASSES[11] == ea.LESS_THAN_9TH_GRADE + assert ea.ACS_SCHL_ATTAINMENT_CLASSES[15] == ea.GRADE_9_TO_12_NO_DIPLOMA + assert ea.ACS_SCHL_ATTAINMENT_CLASSES[17] == ea.HIGH_SCHOOL_GRADUATE + assert ea.ACS_SCHL_ATTAINMENT_CLASSES[19] == ea.SOME_COLLEGE_NO_DEGREE + assert ea.ACS_SCHL_ATTAINMENT_CLASSES[20] == ea.ASSOCIATES_DEGREE + assert ea.ACS_SCHL_ATTAINMENT_CLASSES[21] == ea.BACHELORS_DEGREE + assert ea.ACS_SCHL_ATTAINMENT_CLASSES[23] == ea.GRADUATE_OR_PROFESSIONAL_DEGREE + assert set(ea.ACS_SCHL_ATTAINMENT_CLASSES.values()) == set( + ea.US_EDUCATIONAL_ATTAINMENT_CLASSES + ) + + +def test_both_sources_map_onto_the_same_classes(): + a_hga = set(ea.ASEC_A_HGA_ATTAINMENT_CLASSES.values()) + assert a_hga == set(ea.US_EDUCATIONAL_ATTAINMENT_VALUES) + assert set(ea.ACS_SCHL_ATTAINMENT_CLASSES.values()) | {ea.NOT_IN_UNIVERSE} == a_hga + + +def test_a_hga_refuses_codes_the_dictionary_does_not_list(): + assert list(ea.attainment_from_a_hga([0, 39, 42, 46])) == [ + ea.NOT_IN_UNIVERSE, + ea.HIGH_SCHOOL_GRADUATE, + ea.ASSOCIATES_DEGREE, + ea.GRADUATE_OR_PROFESSIONAL_DEGREE, + ] + for bad in ([30], [47], [-1], [np.nan], [39.5]): + with pytest.raises(ea.EducationalAttainmentError): + ea.attainment_from_a_hga(bad) + + +def test_schl_puts_everyone_under_15_out_of_universe(): + classes = ea.attainment_from_schl(["", "03", "16", "21", "13"], [2, 5, 30, 40, 14]) + assert list(classes) == [ + ea.NOT_IN_UNIVERSE, + ea.NOT_IN_UNIVERSE, + ea.HIGH_SCHOOL_GRADUATE, + ea.BACHELORS_DEGREE, + ea.NOT_IN_UNIVERSE, + ] + with pytest.raises(ea.EducationalAttainmentError, match="blank"): + ea.attainment_from_schl([""], [3]) + with pytest.raises(ea.EducationalAttainmentError): + ea.attainment_from_schl(["25"], [40]) + + +def test_the_six_requested_classes_and_the_roi_classes(): + assert sorted(set(ea.US_EDUCATIONAL_ATTAINMENT_SIX_CLASSES.values())) == sorted( + { + "less_than_high_school", + ea.HIGH_SCHOOL_GRADUATE, + ea.SOME_COLLEGE_NO_DEGREE, + ea.ASSOCIATES_DEGREE, + ea.BACHELORS_DEGREE, + ea.GRADUATE_OR_PROFESSIONAL_DEGREE, + ea.NOT_IN_UNIVERSE, + } + ) + assert dict(ea.US_DEGREE_ROI_CLASSES) == { + "baseline": ea.HIGH_SCHOOL_GRADUATE, + "two_year_degree": ea.ASSOCIATES_DEGREE, + "four_year_degree": ea.BACHELORS_DEGREE, + } + + +def test_s1501_categories_partition_the_classes_in_each_universe(): + categories = ea.S1501_ATTAINMENT_CATEGORY_CLASSES + over_25 = [categories[label] for label in ea.US_EDUCATIONAL_ATTAINMENT_CLASSES] + assert all(len(classes) == 1 for classes in over_25) + under_25 = [ + categories["less_than_high_school_graduate"], + categories[ea.HIGH_SCHOOL_GRADUATE], + categories["some_college_or_associates_degree"], + categories["bachelors_degree_or_higher"], + ] + for universe in (over_25, under_25): + union = set().union(*universe) + assert union == set(ea.US_EDUCATIONAL_ATTAINMENT_CLASSES) + assert sum(len(classes) for classes in universe) == len(union) + + +# --------------------------------------------------------------------------- +# The exact Census join +# --------------------------------------------------------------------------- + + +def _peridnum(index: int) -> str: + return f"{index:022d}" + + +def _member(year: int) -> pd.DataFrame: + """One synthetic Census person member: three people in one household.""" + + return pd.DataFrame( + { + "PERIDNUM": [_peridnum(year * 10 + line) for line in (1, 2, 3)], + "PH_SEQ": [7, 7, 7], + "P_SEQ": [1, 2, 3], + "A_LINENO": [1, 2, 3], + "A_AGE": [44, 41, 9], + "A_HGA": [43, 41, 0], + } + ) + + +def _pin(path, year: int, rows: int) -> AsecSpmRoleSource: + data = path.read_bytes() + return AsecSpmRoleSource( + income_year=year, + survey_year=year + 1, + csv_sha256=hashlib.sha256(data).hexdigest(), + csv_size_bytes=len(data), + persons=rows, + units=1, + official_archive_url="https://example.org/asec.zip", + archive_sha256="0" * 64, + member=f"pppub{str(year + 1)[2:]}.csv", + ) + + +def _write_member(tmp_path, year: int, member: pd.DataFrame | None = None): + member = _member(year) if member is None else member + path = tmp_path / f"pppub{str(year + 1)[2:]}.csv" + member.to_csv(path, index=False) + return path, _pin(path, year, len(member)) + + +def _sources(tmp_path, years=(2023, 2024)) -> pd.DataFrame: + paths, pins = {}, {} + for year in years: + paths[year], pins[year] = _write_member(tmp_path, year) + return ea.load_asec_attainment_sources(years, paths, pins=pins) + + +def _person(year: int, *, clone: bool = True) -> pd.DataFrame: + """The member's people as a pooled frame stores them, plus a PUF clone.""" + + rows = pd.DataFrame( + { + "source_year": year, + "PERIDNUM": [_peridnum(year * 10 + line) for line in (1, 2, 3)], + # Pooling globalizes PH_SEQ; source_household_id keeps Census's. + "PH_SEQ": [900, 900, 900], + "source_household_id": [7, 7, 7], + "P_SEQ": [1, 2, 3], + "A_LINENO": [1, 2, 3], + "A_AGE": [44, 41, 9], + "age": [44.0, 41.0, 9.0], + } + ) + if clone: + rows = pd.concat([rows, rows.iloc[[0]]], ignore_index=True) + return rows + + +def test_every_person_takes_its_own_members_code(tmp_path): + sources = _sources(tmp_path) + person = pd.concat([_person(2023), _person(2024, clone=False)], ignore_index=True) + + a_hga, classes, record = ea.derive_cps_educational_attainment(person, sources) + + assert a_hga.tolist() == [43, 41, 0, 43, 43, 41, 0] + assert classes.tolist() == [ + ea.BACHELORS_DEGREE, + ea.ASSOCIATES_DEGREE, + ea.NOT_IN_UNIVERSE, + ea.BACHELORS_DEGREE, + ea.BACHELORS_DEGREE, + ea.ASSOCIATES_DEGREE, + ea.NOT_IN_UNIVERSE, + ] + assert record["column_role"] == "auxiliary" + assert record["joined_persons_by_income_year"] == {"2023": 4, "2024": 3} + assert set(record["identity_columns_verified"]) == { + "source_household_id", + "P_SEQ", + "A_LINENO", + "A_AGE", + } + assert record["sources"]["2023"]["a_hga_counts"]["43"] == 1 + + +def test_the_join_refuses_a_person_whose_identity_disagrees(tmp_path): + sources = _sources(tmp_path) + person = _person(2023) + person.loc[1, "A_LINENO"] = 5 + with pytest.raises(ea.EducationalAttainmentError, match="A_LINENO"): + ea.derive_cps_educational_attainment(person, sources) + person = _person(2023) + person.loc[0, "source_household_id"] = 8 + with pytest.raises(ea.EducationalAttainmentError, match="source_household_id"): + ea.derive_cps_educational_attainment(person, sources) + + +def test_the_join_checks_raw_ph_seq_on_an_unpooled_table(tmp_path): + sources = _sources(tmp_path) + person = _person(2023).drop(columns="source_household_id") + with pytest.raises(ea.EducationalAttainmentError, match="PH_SEQ"): + ea.derive_cps_educational_attainment(person, sources) + person["PH_SEQ"] = 7 + ea.derive_cps_educational_attainment(person, sources) + + +def test_the_join_refuses_acs_rows_unknown_keys_and_uncovered_years(tmp_path): + sources = _sources(tmp_path) + acs = _person(2023) + acs.loc[2, "PERIDNUM"] = None + with pytest.raises(ea.EducationalAttainmentError, match="SCHL"): + ea.derive_cps_educational_attainment(acs, sources) + unknown = _person(2023) + unknown.loc[2, "PERIDNUM"] = _peridnum(1) + with pytest.raises(ea.EducationalAttainmentError, match="no row"): + ea.derive_cps_educational_attainment(unknown, sources) + with pytest.raises(ea.EducationalAttainmentError, match="2022"): + ea.derive_cps_educational_attainment(_person(2022), sources) + + +def test_the_loader_refuses_a_member_off_its_pin_or_universe(tmp_path): + path, pin = _write_member(tmp_path, 2023) + short = dataclasses.replace(pin, persons=4) + with pytest.raises(ea.EducationalAttainmentError, match="persons"): + ea.load_asec_attainment_sources([2023], {2023: path}, pins={2023: short}) + stale = dataclasses.replace(pin, csv_sha256="1" * 64) + with pytest.raises(ea.EducationalAttainmentError): + ea.load_asec_attainment_sources([2023], {2023: path}, pins={2023: stale}) + + adult_zero = _member(2023) + adult_zero.loc[1, "A_HGA"] = 0 + path, pin = _write_member(tmp_path, 2023, adult_zero) + with pytest.raises(ea.EducationalAttainmentError, match="15 and over"): + ea.load_asec_attainment_sources([2023], {2023: path}, pins={2023: pin}) + + unlisted = _member(2023) + unlisted.loc[0, "A_HGA"] = 47 + path, pin = _write_member(tmp_path, 2023, unlisted) + with pytest.raises(ea.EducationalAttainmentError, match="reviewed Census"): + ea.load_asec_attainment_sources([2023], {2023: path}, pins={2023: pin}) + with pytest.raises(ea.EducationalAttainmentError, match="income year 2031"): + ea.load_asec_attainment_sources([2031]) + + +# --------------------------------------------------------------------------- +# The frame stage and its gate +# --------------------------------------------------------------------------- + + +def _frame(person: pd.DataFrame, weights=None) -> Frame: + n = len(person) + ids = np.arange(1, n + 1, dtype=np.int64) + person = person.copy() + person["person_id"] = ids + person["person_household_id"] = ids + for entity, factor in ( + ("tax_unit", 10), + ("spm_unit", 100), + ("family", 1_000), + ("marital_unit", 10_000), + ): + person[f"person_{entity}_id"] = ids * factor + tables = { + "person": person, + "household": pd.DataFrame( + {"household_id": ids, "state_fips": np.full(n, 6, dtype=np.int64)} + ), + **{ + entity: pd.DataFrame({f"{entity}_id": ids * factor}) + for entity, factor in ( + ("tax_unit", 10), + ("spm_unit", 100), + ("family", 1_000), + ("marital_unit", 10_000), + ) + }, + } + household_weights = ( + np.full(n, 1_000.0) if weights is None else np.asarray(weights, dtype=float) + ) + return Frame( + tables, + US_SCHEMA, + {"household": Weights(household_weights, WeightKind.CALIBRATED)}, + ) + + +def _realistic_person() -> pd.DataFrame: + """Ten adults 25+ in the national mix: one below a diploma, four BA+.""" + + codes = [37, 39, 39, 40, 41, 43, 43, 44, 46, 39] + return pd.DataFrame( + { + "source_year": 2023, + "PERIDNUM": [_peridnum(500 + index) for index in range(10)], + "source_household_id": 5, + "P_SEQ": range(1, 11), + "A_LINENO": range(1, 11), + "A_AGE": 40, + "age": 40.0, + "A_HGA": codes, + } + ) + + +def _realistic_sources(tmp_path, person: pd.DataFrame) -> pd.DataFrame: + member = person.drop(columns=["source_year", "age", "source_household_id"]) + member.insert(1, "PH_SEQ", 5) + path, pin = _write_member(tmp_path, 2023, member) + return ea.load_asec_attainment_sources([2023], {2023: path}, pins={2023: pin}) + + +def test_the_stage_appends_both_columns_and_passes_its_gate(tmp_path): + person = _realistic_person() + sources = _realistic_sources(tmp_path, person) + frame = _frame(person.drop(columns="A_HGA")) + + staged, record = ea.with_us_cps_educational_attainment(frame, sources=sources) + + out = staged.table("person") + assert out["A_HGA"].tolist() == person["A_HGA"].tolist() + assert out[ea.US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN].tolist()[:2] == [ + ea.GRADE_9_TO_12_NO_DIPLOMA, + ea.HIGH_SCHOOL_GRADUATE, + ] + assert record["columns_added"] == ["A_HGA", ea.US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN] + gate = ea.us_cps_educational_attainment_signal_gate(staged) + assert gate.passed, gate.failures + assert gate.details["bachelors_or_higher_share_25_plus"] == pytest.approx(0.4) + assert gate.details["less_than_high_school_share_25_plus"] == pytest.approx(0.1) + + +def test_the_stage_never_overwrites_a_differing_column(tmp_path): + person = _realistic_person() + sources = _realistic_sources(tmp_path, person) + carried = person.copy() + staged, record = ea.with_us_cps_educational_attainment( + _frame(carried), sources=sources + ) + assert record["columns_verified_equal"] == ["A_HGA"] + carried.loc[0, "A_HGA"] = 39 + with pytest.raises(ea.EducationalAttainmentError, match="never overwritten"): + ea.with_us_cps_educational_attainment(_frame(carried), sources=sources) + + +def test_the_gate_refuses_an_implausible_mix(tmp_path): + person = _realistic_person() + person["A_HGA"] = 43 + sources = _realistic_sources(tmp_path, person) + staged, _ = ea.with_us_cps_educational_attainment( + _frame(person.drop(columns="A_HGA")), sources=sources + ) + gate = ea.us_cps_educational_attainment_signal_gate(staged) + assert not gate.passed + assert any("bachelors_or_higher" in failure for failure in gate.failures) + + +# --------------------------------------------------------------------------- +# The S1501 compile path +# --------------------------------------------------------------------------- + + +def _s1501_fact( + *, + category: str, + value: float, + universe: str = "25_plus", + fips: str = "06", + age_constraints: list[dict[str, object]] | None = None, +) -> dict[str, object]: + record_set_id = f"census_acs.acs1_2024.s1501.state_attainment_{universe}.{fips}" + if age_constraints is None: + age_constraints = ( + [{"variable": "age", "operator": ">=", "value": 25, "role": "filter"}] + if universe == "25_plus" + else [ + {"variable": "age", "operator": ">=", "value": 18, "role": "filter"}, + {"variable": "age", "operator": "<", "value": 25, "role": "filter"}, + ] + ) + constraints = list(age_constraints) + if category != "all": + constraints.insert( + 0, + { + "variable": "educational_attainment", + "operator": "==", + "value": category, + "role": "filter", + }, + ) + return _dynamic_ledger_fact( + source_record_id=f"{record_set_id}.{category}.population", + source_name="census_acs", + measure_id="population", + value=value, + period_value=2024, + geography_level="state", + geography_id=f"0400000US{fips}", + groupby_dimension="educational_attainment", + groupby_value_id=category, + layout_record_set_id=record_set_id, + universe_constraints=constraints, + ) + + +def _compile(*facts): + return compile_us_fiscal_target_registry( + [*packaged_reference_facts(), *facts], allow_unaged_dollar_targets=True + ) + + +def test_only_state_25_plus_detail_rows_bind(): + registry = _compile( + _s1501_fact(category=ea.BACHELORS_DEGREE, value=6_355_683), + _s1501_fact(category=ea.ASSOCIATES_DEGREE, value=2_200_000), + _s1501_fact(category="all", value=27_000_000), + _s1501_fact( + category="bachelors_degree_or_higher", value=1, universe="18_to_24" + ), + _s1501_fact(category=ea.BACHELORS_DEGREE, value=5, fips="72"), + ) + attainment = [ + spec + for spec in registry.specs + if spec.family == ea.US_EDUCATIONAL_ATTAINMENT_TARGET_FAMILY + ] + assert sorted(spec.value for spec in attainment) == [2_200_000, 6_355_683] + bachelors = next(spec for spec in attainment if spec.value == 6_355_683) + metadata = bachelors.metadata + assert metadata["materializer"] == ea.US_EDUCATIONAL_ATTAINMENT_TARGET_MATERIALIZER + assert metadata["target_role"] == US_EDUCATIONAL_ATTAINMENT_TARGET_ROLE + assert metadata["measure_mode"] == "indicator_sum" + assert metadata["state_fips"] == "06" + assert metadata["age_lower_bound"] == "25" + assert metadata["age_upper_bound"] == "inf" + assert metadata[ea.US_EDUCATIONAL_ATTAINMENT_CLASSES_METADATA_KEY] == ( + ea.BACHELORS_DEGREE + ) + assert bachelors.name == ( + "census_acs.acs1_2024.s1501.state_attainment_25_plus.06." + "bachelors_degree.population" + ) + names = {spec.name for spec in attainment} + assert {spec.name for spec in registry.specs if "s1501" in spec.name} == names + + +@pytest.mark.parametrize( + ("kwargs", "match"), + [ + ({"category": "doctorate_only"}, "unreviewed attainment category"), + ( + { + "category": ea.BACHELORS_DEGREE, + "age_constraints": [ + {"variable": "age", "operator": ">=", "value": 18, "role": "filter"} + ], + }, + "not the 25_plus universe", + ), + ], +) +def test_a_changed_package_raises_instead_of_binding_wrong(kwargs, match): + with pytest.raises(ValueError, match=match): + _compile(_s1501_fact(value=1, **kwargs)) + + +# --------------------------------------------------------------------------- +# The release tool's materializer +# --------------------------------------------------------------------------- + + +@pytest.fixture(scope="module") +def builder(): + return _load_builder_module() + + +def _attainment_spec(): + registry = _compile(_s1501_fact(category=ea.ASSOCIATES_DEGREE, value=2_200_000)) + return next( + spec + for spec in registry.specs + if spec.family == ea.US_EDUCATIONAL_ATTAINMENT_TARGET_FAMILY + ) + + +def test_the_tool_accepts_the_compiled_age_restatement(builder): + spec = _attainment_spec() + assert spec.metadata["ledger_filter_age_lower_bound"] == "25" + assert builder._unsupported_ledger_filter_metadata([spec]) == {} + + +def test_the_tool_counts_persons_in_class_band_and_state(builder): + spec = _attainment_spec() + person = pd.DataFrame( + { + ea.US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN: [ + ea.ASSOCIATES_DEGREE, + ea.ASSOCIATES_DEGREE, + ea.BACHELORS_DEGREE, + ea.ASSOCIATES_DEGREE, + ], + "age": [30.0, 24.0, 50.0, 60.0], + } + ) + frame = _frame(person) + household = frame.table("household").copy() + household.loc[3, "state_fips"] = 36 + values = builder._population_attainment_household_values( + frame=frame, + household=household, + age=person["age"].to_numpy(), + metadata=spec.metadata, + ) + assert values.tolist() == [1.0, 0.0, 0.0, 0.0] + with pytest.raises(RuntimeError, match="--cps-educational-attainment"): + builder._population_attainment_household_values( + frame=_frame(person.drop(columns=ea.US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN)), + household=household, + age=person["age"].to_numpy(), + metadata=spec.metadata, + ) + + +def test_the_tool_parses_attainment_sources(builder): + assert builder._asec_attainment_source_paths(["2024=a.zip", "2023=b.csv"]) == { + 2024: Path("a.zip"), + 2023: Path("b.csv"), + } + for bad in (["2024"], ["x=a.zip"], ["2024=a", "2024=b"]): + with pytest.raises(SystemExit): + builder._asec_attainment_source_paths(bad) + args = builder._parse_args( + [ + "--ledger-facts", + "facts.jsonl", + "--out", + "release", + "--cps-educational-attainment", + "--asec-attainment-source", + "2024=a.zip", + ] + ) + assert args.cps_educational_attainment + assert args.asec_attainment_source == ["2024=a.zip"] diff --git a/packages/microcosm-build/tests/engine_free/us/test_us_stored_input_register.py b/packages/microcosm-build/tests/engine_free/us/test_us_stored_input_register.py index e25bc2619a..536dfb4021 100644 --- a/packages/microcosm-build/tests/engine_free/us/test_us_stored_input_register.py +++ b/packages/microcosm-build/tests/engine_free/us/test_us_stored_input_register.py @@ -30,7 +30,7 @@ def test_every_register_entry_is_a_named_producer_column(): base-spine tag of every US entity, the pooled-source provenance columns, microunit's two tax-unit construction columns, the PUF capital-gains tail provenance columns, the ACS-native acs_ amounts and acs_pums's puma_geoid - alias.""" + alias, plus the pending parent ids and the auxiliary attainment class.""" support = { column(entity) @@ -61,9 +61,10 @@ def test_every_register_entry_is_a_named_producer_column(): | _ACS_NATIVE_AMOUNTS | {"puma_geoid"} | set(US_ELIGIBILITY_INPUTS_PARENT_ID_COLUMNS) + | {US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN} ) assert len(_ACS_NATIVE_AMOUNTS) == 6 - assert len(US_STORED_NON_VARIABLE_COLUMNS) == 30 + 6 + 6 + 6 + 1 + 2 + assert len(US_STORED_NON_VARIABLE_COLUMNS) == 30 + 6 + 6 + 6 + 1 + 2 + 1 def test_every_register_reason_names_where_its_column_comes_from(): @@ -96,6 +97,9 @@ def test_every_register_reason_names_where_its_column_comes_from(): column: "US_ELIGIBILITY_INPUTS_PARENT_ID_COLUMNS" for column in US_ELIGIBILITY_INPUTS_PARENT_ID_COLUMNS }, + US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN: ( + "microcosm.build.us_runtime.educational_attainment" + ), } for column, owner in expected_owner.items(): assert owner in US_STORED_NON_VARIABLE_COLUMNS[column], column @@ -726,3 +730,21 @@ def fail(*args, **kwargs): ) == [] ) + + +def test_the_auxiliary_columns_are_flagged_and_registered(): + """microcosm#297: an auxiliary column is a register entry whose reason says + so, and the attainment class is the only one.""" + + assert set(US_AUXILIARY_STORED_COLUMNS) == {US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN} + for column, reason in US_AUXILIARY_STORED_COLUMNS.items(): + assert US_STORED_NON_VARIABLE_COLUMNS[column] == reason + assert reason.startswith("Auxiliary: ") + assert "no rule reads it" in reason + non_auxiliary = set(US_STORED_NON_VARIABLE_COLUMNS) - set( + US_AUXILIARY_STORED_COLUMNS + ) + assert not any( + US_STORED_NON_VARIABLE_COLUMNS[column].startswith("Auxiliary") + for column in non_auxiliary + ) diff --git a/packages/microcosm-calibrate/src/microcosm/calibrate/variable_labels.py b/packages/microcosm-calibrate/src/microcosm/calibrate/variable_labels.py index 32a1425bdf..44e0012352 100644 --- a/packages/microcosm-calibrate/src/microcosm/calibrate/variable_labels.py +++ b/packages/microcosm-calibrate/src/microcosm/calibrate/variable_labels.py @@ -51,6 +51,7 @@ def _immutable_registry( "wages_and_salaries_projection": "Wages and salaries projection", }, "census_acs": { + "educational_attainment": "Educational attainment", "resident_population": "Resident population", }, "census_pep": { diff --git a/packages/microcosm-calibrate/tests/engine_free/shared/test_variable_labels.py b/packages/microcosm-calibrate/tests/engine_free/shared/test_variable_labels.py index 41654f1835..7f3e708cf2 100644 --- a/packages/microcosm-calibrate/tests/engine_free/shared/test_variable_labels.py +++ b/packages/microcosm-calibrate/tests/engine_free/shared/test_variable_labels.py @@ -26,6 +26,7 @@ def _pairs(value: str) -> set[tuple[str, str]]: cbo|net_capital_gain_projection cbo|qualified_dividend_income_projection cbo|wages_and_salaries_projection +census_acs|educational_attainment census_acs|resident_population census_pep|resident_population census_stc|individual_income_tax_collections diff --git a/packages/microcosm-data/src/microcosm/data/stored_inputs.py b/packages/microcosm-data/src/microcosm/data/stored_inputs.py index 5193e0cfcc..5dff2a1d70 100644 --- a/packages/microcosm-data/src/microcosm/data/stored_inputs.py +++ b/packages/microcosm-data/src/microcosm/data/stored_inputs.py @@ -118,6 +118,7 @@ __all__ = [ "MODEL_NAMED_COLUMN_PATTERN", + "US_AUXILIARY_STORED_COLUMNS", "US_STORED_NON_VARIABLE_COLUMNS", "CertifiedEngine", "StoredInputRefusalError", @@ -259,6 +260,33 @@ #: register entry to the producer definition it names. _US_ENTITIES = ("person", "household", "tax_unit", "spm_unit", "family", "marital_unit") +#: Auxiliary columns: person attributes a build carries for conditioning +#: (imputation predictors) and calibration (target margins) that no rule +#: consumes, so their presence is not a tax-benefit modeling claim +#: (microcosm#297). Unlike a pending engine input, an auxiliary column is not +#: waiting for an engine variable, so its entry does not expire with an engine +#: bump; an analysis reads it by joining on ``person_id``. Each is part of +#: :data:`US_STORED_NON_VARIABLE_COLUMNS`, and its reason starts with +#: ``Auxiliary``. +US_AUXILIARY_STORED_COLUMNS: Mapping[str, str] = MappingProxyType( + { + "cps_educational_attainment": ( + "Auxiliary: the person's highest completed education level, one of " + "seven classes (the ACS S1501 population-25-and-over categories) or " + "not_in_universe under age 15, classified from the CPS ASEC A_HGA " + "code that an exact (income year, PERIDNUM) join reads from the " + "pinned official Census person member, written by " + "microcosm.build.us_runtime.educational_attainment " + "(US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN; microcosm#297) when the " + "fiscal-refresh build runs with --cps-educational-attainment. It " + "conditions imputation and binds the ACS S1501 state attainment " + "targets; no rule reads it, and policyengine-us defines no " + "variable for it." + ), + } +) + + #: Reviewed register of lowercase stored columns that are deliberately not #: policyengine-us variables: column -> why the engine may ignore it. #: @@ -284,7 +312,9 @@ #: (microcosm#884). No examined file stores them yet, so they rest on their #: live producer, ``eligibility_inputs.US_ELIGIBILITY_INPUTS_PARENT_ID_COLUMNS``, #: which ``test_us_stored_input_register.py`` binds, and leave the register -#: once the pinned engine defines them. +#: once the pinned engine defines them. The auxiliary columns +#: (:data:`US_AUXILIARY_STORED_COLUMNS`) postdate the files too and rest on +#: their producer the same way. #: #: Two model-named non-variable columns that the published default, its #: receipt child and the ACS local-area release store are deliberately absent, @@ -319,6 +349,7 @@ #: that rule against the installed engine. US_STORED_NON_VARIABLE_COLUMNS: Mapping[str, str] = MappingProxyType( { + **US_AUXILIARY_STORED_COLUMNS, **{ f"{entity}_source_id": _SUPPORT_SOURCE_ID.format(entity=entity) for entity in _US_ENTITIES diff --git a/test_support/microcosm_build/us_stored_input_register.py b/test_support/microcosm_build/us_stored_input_register.py index 91c008846b..1a59d4d58d 100644 --- a/test_support/microcosm_build/us_stored_input_register.py +++ b/test_support/microcosm_build/us_stored_input_register.py @@ -27,6 +27,9 @@ from microcosm.build.us_runtime import acs_pums, acs_transfer from microcosm.build.us_runtime import puf_capital_gains_tail as puf_tail from microcosm.build.us_runtime.base_pool import spine_column +from microcosm.build.us_runtime.educational_attainment import ( + US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN, +) from microcosm.build.us_runtime.eligibility_inputs import ( US_ELIGIBILITY_INPUTS_PARENT_ID_COLUMNS, ) @@ -39,6 +42,7 @@ ) from microcosm.data.stored_inputs import ( _US_ENTITIES, + US_AUXILIARY_STORED_COLUMNS, US_STORED_NON_VARIABLE_COLUMNS, CertifiedEngine, h5_stored_tables, diff --git a/test_support/microcosm_data/stored_inputs.py b/test_support/microcosm_data/stored_inputs.py index 4206bdf943..575c3d2cd5 100644 --- a/test_support/microcosm_data/stored_inputs.py +++ b/test_support/microcosm_data/stored_inputs.py @@ -155,9 +155,13 @@ def _column_strategies(st): #: Register entries that postdate the files examined for #1026 and rest on a #: live producer instead: the parent ids (microcosm#884), bound to -#: eligibility_inputs.US_ELIGIBILITY_INPUTS_PARENT_ID_COLUMNS by +#: eligibility_inputs.US_ELIGIBILITY_INPUTS_PARENT_ID_COLUMNS, and the +#: auxiliary attainment class (microcosm#297), bound to +#: educational_attainment.US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN, both by #: test_us_stored_input_register.py (microcosm-data cannot import the build). -_PRODUCER_BOUND_ENTRIES = frozenset({"parent_1_id", "parent_2_id"}) +_PRODUCER_BOUND_ENTRIES = frozenset( + {"parent_1_id", "parent_2_id", "cps_educational_attainment"} +) #: The role columns policyengine-core's ``build_from_dataset`` reads to build diff --git a/tools/build_us_fiscal_refresh_release.py b/tools/build_us_fiscal_refresh_release.py index 44bebf56c4..ec106d9142 100644 --- a/tools/build_us_fiscal_refresh_release.py +++ b/tools/build_us_fiscal_refresh_release.py @@ -239,6 +239,14 @@ population_by_age_from_sim, write_demographics, ) +from microcosm.build.us_runtime.educational_attainment import ( + US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN, + US_EDUCATIONAL_ATTAINMENT_TARGET_MATERIALIZER, + attainment_target_person_indicator, + load_asec_attainment_sources, + us_cps_educational_attainment_signal_gate, + with_us_cps_educational_attainment, +) from microcosm.build.us_runtime.engine_lifecycle import release_engine_simulation from microcosm.build.us_runtime.exact_k_ladder import ( ExactKLadderCalibration, @@ -861,15 +869,23 @@ def _automatic_gc_suspended(): } #: Materializers that apply the compiled age band, and so the only ones for -#: which ignoring an agreeing age restatement changes nothing. Both are read -#: in :func:`_materialize_target_frame`: ``population_age`` through -#: :func:`_population_age_household_values`, and ``policyengine_variable`` +#: which ignoring an agreeing age restatement changes nothing. All three are +#: read in :func:`_materialize_target_frame`: ``population_age`` through +#: :func:`_population_age_household_values`, ``policyengine_variable`` #: through its age-banded branch, entered whenever either compiled age key is -#: present. Every other materializer (the ``irs_soi`` slice, the direct +#: present, and the ACS S1501 attainment counts (``population_attainment``, +#: microcosm#297) through :func:`_population_attainment_household_values`, +#: which applies the same half-open band. Every other materializer (the ``irs_soi`` slice, the direct #: household-variable measures) never reads an age bound, so a restated age #: bound there would be silently ignored however well it agreed with metadata #: the materializer also ignores; it is refused instead. -RESTATED_AGE_BAND_MATERIALIZERS = frozenset({"population_age", "policyengine_variable"}) +RESTATED_AGE_BAND_MATERIALIZERS = frozenset( + { + "population_age", + "policyengine_variable", + US_EDUCATIONAL_ATTAINMENT_TARGET_MATERIALIZER, + } +) #: The exact-value age key the dimension stamp writes when ``age`` is itself #: a dimension of the fact. @@ -1602,6 +1618,30 @@ def _parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace: "interest. When omitted, scf2022s.zip is fetched and cached." ), ) + parser.add_argument( + "--cps-educational-attainment", + action="store_true", + help=( + "Carry the auxiliary person column cps_educational_attainment " + "(and the raw Census A_HGA it is classified from) by an exact " + "(income year, PERIDNUM) join to the pinned official CPS ASEC " + "person members (microcosm#297). Auxiliary: no rule reads it; it " + "conditions imputation and lets ACS S1501 state attainment targets " + "bind. Refuses ACS-spine rows, which carry no PERIDNUM." + ), + ) + parser.add_argument( + "--asec-attainment-source", + action="append", + default=[], + metavar="YEAR=PATH", + help=( + "Optional INCOME_YEAR=PATH mapping to a local copy of the pinned " + "official ASEC person archive (asecpubYYcsv.zip) or its person " + "CSV, for --cps-educational-attainment. Unmapped income years are " + "fetched from census.gov and verified against the same pins." + ), + ) parser.add_argument( "--sipp-tip-donor", type=Path, @@ -5752,6 +5792,44 @@ def _population_age_household_values( return values +def _population_attainment_household_values( + *, + frame: Frame, + household: pd.DataFrame, + age: np.ndarray, + metadata: Mapping[str, str], +) -> np.ndarray: + """Household counts of the persons an ACS S1501 attainment cell counts. + + The cell counts persons in its half-open age band whose auxiliary + ``cps_educational_attainment`` class is one the target names + (microcosm#297), in its state. A frame without the column cannot + materialize the target, so it refuses rather than binding zeros. + """ + + person = frame.table("person") + if US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN not in person.columns: + raise RuntimeError( + "ACS S1501 attainment targets require the auxiliary person column " + f"{US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN}; build with " + "--cps-educational-attainment." + ) + indicator = attainment_target_person_indicator( + person[US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN].to_numpy(), + age, + metadata, + ) + values = _collapse_person(frame, indicator) + state_fips = metadata.get("state_fips") + if not state_fips: + raise RuntimeError("ACS S1501 attainment targets are state-grain.") + return np.where( + household["state_fips"].to_numpy() == int(state_fips), + values, + 0.0, + ) + + def _restated_ledger_filter_concept(key: str) -> tuple[str, str | None]: """Split a ``ledger_filter_*`` key into its concept and bound side. @@ -6275,6 +6353,21 @@ def _base_simulation_household_columns( household_congressional_district_geoid ), ) + attainment_target_specs = [ + spec + for spec in target_specs + if spec.metadata.get("materializer") + == US_EDUCATIONAL_ATTAINMENT_TARGET_MATERIALIZER + ] + if attainment_target_specs: + person_age = np.asarray(_calculate_array(simulation, "age"), dtype=np.float64) + for spec in attainment_target_specs: + columns[spec.measure] = _population_attainment_household_values( + frame=frame, + household=household, + age=person_age, + metadata=spec.metadata, + ) direct_target_specs = [ spec for spec in target_specs @@ -12485,6 +12578,93 @@ def _check_committed_us_ledger_feed_pin( ) +def _asec_attainment_source_paths(entries: Sequence[str]) -> dict[int, Path]: + """Map each --asec-attainment-source INCOME_YEAR=PATH; refuse bad or repeated.""" + + paths: dict[int, Path] = {} + for entry in entries: + year, separator, path = str(entry).partition("=") + if not separator or not year.strip().isdigit() or not path: + raise SystemExit( + f"error: --asec-attainment-source must be INCOME_YEAR=PATH, got {entry!r}" + ) + income_year = int(year) + if income_year in paths: + raise SystemExit( + f"error: --asec-attainment-source repeats income year {income_year}" + ) + paths[income_year] = Path(path) + return paths + + +def _with_cps_educational_attainment_stage( + base_frame: Frame, + *, + args: argparse.Namespace, + telemetry: Any, + receipt_path: Path | None, +) -> Frame: + """Join the auxiliary attainment class and run its signal gate (#297).""" + + if telemetry is not None: + telemetry.stage( + "cps_educational_attainment", + message=( + "Joining CPS ASEC A_HGA by (income year, PERIDNUM) and carrying " + "the auxiliary cps_educational_attainment class." + ), + ) + person = base_frame.table("person") + if "source_year" not in person.columns: + raise RuntimeError( + "--cps-educational-attainment requires the person source_year column." + ) + sources = load_asec_attainment_sources( + pd.to_numeric(person["source_year"], errors="raise").astype(int).unique(), + _asec_attainment_source_paths(args.asec_attainment_source), + ) + base_frame, record = with_us_cps_educational_attainment(base_frame, sources=sources) + gate = us_cps_educational_attainment_signal_gate(base_frame) + if not gate.passed: + if telemetry is not None: + telemetry.stage( + "cps_educational_attainment_gate", + status="failed", + message="CPS educational-attainment signal gate failed.", + failures=list(gate.failures), + force_upload=True, + ) + raise RuntimeError( + "Release gates failed: " + + "; ".join( + f"CPS educational-attainment signal failed: {failure}" + for failure in gate.failures + ) + ) + if receipt_path is not None: + receipt_path.parent.mkdir(parents=True, exist_ok=True) + receipt_path.write_text( + json.dumps( + { + "schema_version": 1, + "column": US_CPS_EDUCATIONAL_ATTAINMENT_COLUMN, + "column_role": "auxiliary", + "derivation": record, + "signal_gate": { + "passed": gate.passed, + "details": dict(gate.details), + }, + }, + indent=2, + sort_keys=True, + default=float, + ) + + "\n", + encoding="utf-8", + ) + return base_frame + + def _main(argv: Sequence[str] | None = None) -> int | None: global _ACTIVE_EMITTER, _ACTIVE_PROGRESS _ACTIVE_EMITTER = None @@ -13687,6 +13867,19 @@ def _main(argv: Sequence[str] | None = None) -> int | None: for failure in education_inputs_gate.failures ) ) + if args.cps_educational_attainment: + # microcosm#297: auxiliary attainment class for conditioning and the + # ACS S1501 state attainment targets; no rule reads it. + base_frame = _with_cps_educational_attainment_stage( + base_frame, + args=args, + telemetry=telemetry, + receipt_path=( + artifact_root / "us_cps_educational_attainment.json" + if dry_run is None + else None + ), + ) if telemetry is not None: telemetry.stage( "pregnancy_inputs",