Skip to content

Add new Commerce EDA Poverty import - #2178

Open
shvngisingh wants to merge 39 commits into
datacommonsorg:masterfrom
shvngisingh:commerce_eda_poverty_import
Open

shvngisingh wants to merge 39 commits into
datacommonsorg:masterfrom
shvngisingh:commerce_eda_poverty_import

Conversation

@shvngisingh

@shvngisingh shvngisingh commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor

Overview

Adds the automated import and validation configuration for Commerce_EDA_Poverty (statvar_imports/commerce_eda_poverty), which ingests county-level and island-territory poverty percentage rates from the U.S. Economic Development Administration (EDA) Persistent Poverty Counties (PPCs) dataset (EDA_FY23_PPCs.xlsx).

Key Changes

  1. Download Pipeline (download_poverty.py & download_poverty_test.py):

    • Downloads the official EDA_FY23_PPCs.xlsx workbook from eda.gov (with automatic fallback to the Wayback Machine mirror if bot protection blocks automated requests, or local file ingestion via --input_file) by delegating HTTP requests to util.download_util.request_url.
    • Verifies the ZIP/XLSX magic-byte header (PK\x03\x04) before atomically saving input_files/EDA_FY23_PPCs.xlsx and extracting the Underlying_Data worksheet into input_files/Poverty.csv.
    • Defaults raw_csv_path to None so an unused duplicate CSV is not written to output/Poverty_original.csv unless explicitly requested.
  2. Preprocessing & PV Mapping (process_poverty.py, process_poverty_test.py, & poverty_pvmap.csv):

    • Dynamically locates the GEOID header row, standardizes 5-digit county and island-territory FIPS codes (filtering out state-level XX000 summary rows), and validates percentage bounds within [0.0, 100.0].
    • Reshapes wide historical Decennial Census columns (1990, 2000, and any future <YEAR> ... % in Poverty columns) and recent estimates (2020 Island Areas Decennial Census for AS, GU, MP, VI; 2021 SAIPE / ACS 5-Year for the 50 states, DC, and PR) into normalized (GEOID, year, poverty_rate) rows.
    • Deduplicates observations by ["GEOID", "year"] while preserving deterministic input row ordering.
    • Maps Decennial Census benchmark years (1990, 2000, 2010, 2020, 2030, 2040, 2050) to measurementMethod: dcs:USDecennialCensus and SAIPE/ACS years (2021 and default) to measurementMethod: dcs:EDA_Estimate in poverty_pvmap.csv.
  3. Manifest & Validation Configuration (manifest.json & validation_config.json):

    • Configures node_mcf: "output/*.mcf" in manifest.json and restricts source_files to raw inputs, counters, and validation_config.json.
    • Configures 3 validation rules in validation_config.json (in addition to the 3 built-in runner checks):
      • check_date_span_sql (SQL_VALIDATOR): Verifies CAST(MinDate AS INTEGER) <= 1990 AND CAST(MaxDate AS INTEGER) >= 2021 AND total_svs > 0.
      • check_max_date_consistent (MAX_DATE_CONSISTENT): Verifies uniform MaxDate across all statistical variables (2021).
      • check_deleted_records_percent (DELETED_RECORDS_PERCENT): Enforces threshold: 0.1 (0.1% maximum deleted records).

Test Environment Verification (datcom-infosys-dev)

  • Batch Job ID: commerce-eda-poverty-shvngisingh-20261022-072318 (SUCCEEDED, ImportStatus.STAGING, 9,689 rows processed, 0 lint errors)
  • Validation Result: 6/6 rules PASSED (check_deleted_records_percent, check_empty_import, check_missing_refs_count, check_lint_error_count, check_date_span_sql, check_max_date_consistent)
  • Batch Job Execution Logs: link
  • GCS Test Output Folder (2026_10_22T00_27_19_036019_07_00): link
  • Validation Output (validation_output.csv): link
  • Differ Summary (differ_summary.json): link
  • GenMCF Summary Report (summary_report.csv):link
  • GenMCF Report JSON (report.json): link

Local Unit Tests

python3 -m unittest discover -s statvar_imports/commerce_eda_poverty -p "*test*.py" -v
# Ran 30 tests in 0.244s — OK

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new data importer for the Commerce EDA Poverty dataset, which tracks Persistent Poverty Counties. It includes metadata, mapping files, generated outputs, and a preprocessing script (process_poverty.py). The review feedback identifies two key issues: a hardcoded absolute project path in the preprocessing script that will cause failures in other environments, and an incorrect place type (AdministrativeArea1 instead of County) in the commented-out metadata configuration.

Comment thread statvar_imports/commerce_eda_poverty/process_poverty.py Outdated
Comment thread statvar_imports/commerce_eda_poverty/Povertymetadata.csv Outdated
@shvngisingh
shvngisingh force-pushed the commerce_eda_poverty_import branch from 5248291 to 1196449 Compare August 24, 2026 07:53
Comment thread statvar_imports/commerce_eda_poverty/counters/Poverty_counters.csv Outdated
Comment thread statvar_imports/commerce_eda_poverty/output/Poverty_cleaned.csv Outdated
Comment thread statvar_imports/commerce_eda_poverty/poverty_metadata.csv
Comment thread statvar_imports/commerce_eda_poverty/poverty_pvmap.csv
…ty rates, untrack output/counters, rename metadata/pvmap, add test fixtures
…g.error+raise, add validation rule descriptions
…schedule, map variableMeasured directly in pvmap, reject XX000 FIPS, restore GCS retries, and add survey year guard
Comment thread statvar_imports/commerce_eda_poverty/test_data/Poverty_input.csv
Comment thread statvar_imports/commerce_eda_poverty/README.md Outdated

@saanikaaa saanikaaa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is new import, we should have a CL as well to bring textproto. Mcf and dataset info about this import

… document semi-automated GCS setup in README
- Add download_poverty.py (and download.py alias) to dynamically discover and download the Persistent Poverty Counties Excel workbook directly from the Treasury CDFI Fund website with retries and exponential backoff
- Refactor process_poverty.py to ingest the downloaded source file locally from input_files/ and eliminate all GCS bucket dependencies
- Add download_poverty_test.py and update process_poverty_test.py with unit tests for download, retry, and local file preprocessing
- Update manifest.json scripts to execute download_poverty.py followed by process_poverty.py
- Update README.md to document the automated source download and preprocessing workflow
…verty Counties dataset

- Add download_poverty.py (and download.py alias) to download the official EDA_FY23_PPCs.xlsx dataset directly from EDA website or archive mirror with retries, and support local --input_file
- Extract Underlying_Data sheet from EDA_FY23_PPCs.xlsx to input_files/Poverty.csv and stage output/Poverty_original.csv
- Refactor process_poverty.py to dynamically resolve source file (local Excel or CSV) and dynamically detect header row containing GEOID
- Standardize 5-digit county GEOIDs (filtering state summary 01000 codes) and partition poverty_rate_recent into 2020 (island territories) and 2021 (states, DC, PR)
- Restore 3,232-county dataset coverage across 1990, 2000, 2020, and 2021 observation dates
- Restore validation_config.json thresholds for full county coverage (3100-3250 places, 9000-10000 observations)
- Restore test fixtures test_data/Poverty_input.csv and test_data/Poverty_expected_output.csv
- Add comprehensive unit tests in download_poverty_test.py and process_poverty_test.py (all 22 passing)
- Update README.md and manifest.json with EDA provenance and usage instructions
Comment thread statvar_imports/commerce_eda_poverty/download_poverty_test.py Fixed
… Poverty

- Remove check_deleted_records_percent for new import (FINDING-P1-01)
- Remove deceptive test fixture fallback from download and process scripts (FINDING-P2-01)
- Add golden_summary_report.csv and wire check_goldens_summary_report rule (FINDING-P2-02)
- Include output/*.mcf and counters/* in manifest.json source_files (FINDING-P2-03)
- Refactor download_poverty.py to use requests session retry adapter and fast fail on 404 (FINDING-P2-04)
- Add Troubleshooting Runbook and GCP credential prerequisite to README.md (FINDING-P2-05)
- Wrap long lines (>100 chars) in config and test files (FINDING-P3-01)
- Add PEP 8 import blank line separations (FINDING-P3-02)
- Close openpyxl workbooks and requests sessions in try-finally blocks (FINDING-P3-03)
- Remove unused output_dir flag definition (FINDING-P3-04)
- Rename check_num_observations_check to check_num_observations_count (FINDING-P3-05)
…A Poverty

- Eliminate dual-layered retry loop in download_poverty.py and rely on requests HTTPAdapter ([P3-01])
- Add standalone CLI test runner bootstrap to download_poverty_test.py and update transport mock tests ([P3-02])
- Use file handle for df.to_csv and robust cleanup on exception in process_poverty.py ([P3-03])
- Clean up existing target files before fresh download in download_poverty.py and eliminate post-loop stale file fallback.
- Wrap requests session and streaming responses in context managers to prevent socket leaks and ResourceWarnings.
- Validate survey year within dynamic integer range [2020..current year] with configurable flags in process_poverty.py.
- Align release cadence to annual (P1Y, cron: 30 05 1 1 *) in manifest.json and poverty_metadata.csv.
- Update provenance URL to https://www.eda.gov/performance/resources/persistent-poverty-counties.
- Update README.md to document 5-digit county and island territory FIPS resolution, Cloudflare protection, and validation rules.
- Add unit tests for download error handling, stale cleanup, and survey year range validation.
Comment thread statvar_imports/commerce_eda_poverty/process_poverty.py Fixed
Comment thread import-automation/executor/requirements.txt Outdated
Comment thread statvar_imports/commerce_eda_poverty/test_data/Poverty_input.csv
Comment thread statvar_imports/commerce_eda_poverty/download_poverty.py
Comment thread statvar_imports/commerce_eda_poverty/manifest.json
Comment thread statvar_imports/commerce_eda_poverty/validation_config.json Outdated
Comment thread statvar_imports/commerce_eda_poverty/validation_config.json
Comment thread statvar_imports/commerce_eda_poverty/process_poverty.py Outdated
Comment thread statvar_imports/commerce_eda_poverty/process_poverty.py
Comment thread statvar_imports/commerce_eda_poverty/process_poverty.py
…verty import

- Bump datacommons to 1.4.4 in executor requirements.txt
- Use util.download_util.download_file_from_url in download_poverty.py and update unit tests
- Dynamically scan for GEOID header in process_poverty.py instead of fixed 10-row loops
- Update empty DataFrame error message to 'File not read properly into dataframe'
- Document in README.md and process_poverty.py why preprocessing is required before PV mapping
- Update source_files in manifest.json to only reference raw input dataset
- Add check_deleted_records_percent (threshold: 0) and remove maximum observation ceiling in validation_config.json
- Trim test data files (Poverty_input.csv to 39 rows, Poverty_expected_output.csv to 91 rows)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants