# Metro Nashville ACFR / CAFR statistical-section extraction

Tidy, long-format CSVs built from the "Last Ten Fiscal Years" trend tables in the statistical section (Section H)
of the Metropolitan Government of Nashville and Davidson County annual financial reports. Source PDFs are in
`raw/acfr/`; scripts are in `scripts/acfr/` (`extract_acfr.py` rebuilds everything, `validate_acfr.py` re-runs the
checks, `spot_check.py` prints random values next to the PDF text line they came from).

## Files

| file | content | years | reports used |
|---|---|---|---|
| `changes_in_net_position.csv` | government-wide (accrual) expenses by function, business-type expenses, program revenues (charges for services by function, operating/capital grants), net (expense) revenue, general revenues by type, change in net position | FY2002–FY2025 | FY2010, FY2015, FY2020, FY2024, FY2025 (primary) + FY2016–FY2019, FY2021–FY2023 (cross-checks) |
| `changes_in_fund_balances.csv` | governmental funds (modified accrual): revenues by source, expenditures by function, debt service, capital outlay, other financing sources (uses), net change in fund balances, debt service as % of noncapital(ized) expenditures | FY2001–FY2025 | same twelve reports |
| `fund_balances.csv` | `table = fund_balances`: fund balances of governmental funds (general fund components, all other governmental funds, total); `table = fund_balances_budgeted`: budgeted governmental funds with GSD / USD split, school fund and three debt service funds | FY2001–FY2025 | FY2010, FY2015, FY2025 |
| `property_tax.csv` | GSD and USD assessed value by class (realty / personalty / public utility), estimated actual value, assessed-to-actual %, tax rates by fund (GSD, USD, combined direct rate), levies and collections (levy, collected in year of levy, %, adjustments, collections to date, outstanding delinquent) | FY2001–FY2025 | FY2010, FY2015, FY2025 |
| `debt.csv` | ratios of outstanding debt by type (each debt type, totals, % of personal income, per capita), general bonded debt (GSD+USD and USD-only; total, % of estimated actual value, per capita), ratio of debt service to total general expenditures | FY2001–FY2025 | FY2010, FY2015, FY2025 |
| `demographics.csv` | population, per capita personal income, personal income, unemployment rate — by **calendar year** (`calendar_year` column) | CY2000–CY2024 | FY2010, FY2015, FY2020, FY2024, FY2025 |
| `fte_by_function.csv` | full-time-equivalent employees by function (governmental, internal service, business-type, totals) | FY2001–FY2025 | FY2010, FY2015, FY2020, FY2024, FY2025 |
| `operating_indicators.csv` | `table = operating_indicators`: every line of Operating Indicators by Function; `table = capital_asset_statistics`: Capital Asset Statistics by Function (FY2001–FY2024; the FY2025 ACFR has no capital-asset schedule) | FY2001–FY2025 | FY2010, FY2015, FY2020, FY2024, FY2025 |
| `restatements.csv` | every (table, year, section, line) that appears in more than one report with different values: preferred (most recent) value, each other report's value, difference, % change | | |
| `line_presence_differences.csv` | lines reported for a year in some reports but absent from other reports covering that year (renamed / folded lines) | | |
| `validation_report.txt` | full output of `validate_acfr.py` | | |
| `_extraction_log.json` | parser warnings (none) and the footnote text captured on every table page | | |

Columns (all files): `source_report`, `fiscal_year` (or `calendar_year`), `table`, `section` (the heading path the line sits
under, e.g. `Expenses > Governmental activities`), `line_item` (the report's own wording), `amount` (float, in `unit`),
`unit`, `footnote` (text of every numbered footnote attached to that year column or line, else blank), plus two
traceability columns: `pdf_page` (1-based page in the source PDF) and `raw` (the token as printed, e.g. `(1,234)`).
`-` in the report = 0.0; `N/A` = empty amount (63 in debt, 8 in demographics, 35 in operating indicators).

## Units

* Changes in net position: **thousands of dollars**. Debt tables: **thousands**, except per-capita amounts (dollars) and percentages.
* Changes in fund balances, fund balances, assessed values, levies: **whole dollars**. Tax rates: dollars per $100 of assessed value (`rate per $100`).
* Debt service ratio in changes_in_fund_balances: `percent` (older reports print two decimals, FY2022+ print whole percents — see restatements).
* Demographics: population `count`, per capita income `dollars`, personal income `thousands`, unemployment `percent`.
* FTE and operating indicators: `count`, except lines whose label carries a unit in parentheses (millions of gallons per day, thousand pounds, thousand ton hours).

## Page map (pdf page numbers, 1-based)

| report | changes in net position | changes in fund balances | fund balances / budgeted | assessed value GSD / USD | tax rates | levies & collections | outstanding debt | bonded debt GSD+USD / USD | debt service ratio | demographics | FTE | operating indicators | capital assets |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ACFR_FY2025 | 319–322 | 327–330 | 323–324 / 325–326 | 331–332 / 333 | 334 | 337–338 | 339–340 | 341 / 342 | 345 | 347 | 349–350 | 351–354 | none |
| ACFR_FY2024 | 313–316 | 321–324 | – | – | – | – | – | – | – | 341 | 343–344 | 345–348 | 351–352 |
| ACFR_FY2023 | 316–319 | 324–327 | | | | | | | | | | | |
| ACFR_FY2022 | 316–319 | 324–327 | | | | | | | | | | | |
| ACFR_FY2021 | 274–277 | 282–285 | | | | | | | | | | | |
| CAFR_FY2020 | 270–273 | 278–281 | – | – | – | – | – | – | – | 298 | 300–301 | 302–305 | – |
| CAFR_FY2019 | 268–271 | 276–279 | | | | | | | | | | | |
| CAFR_FY2018 | 268–271 | 276–279 | | | | | | | | | | | |
| CAFR_FY2017 | 278–281 | 286–289 | | | | | | | | | | | |
| CAFR_FY2016 | 278–281 | 286–289 | | | | | | | | | | | |
| CAFR_FY2015 | 276–279 | 284–287 | 280–281 / 282–283 | 288–289 / 290 | 291 | 294–295 | 296–297 | 298 / 299 | 302 | 304 | 306–307 | 308–311 | 312–313 |
| CAFR_FY2010 | 269–272 ("Changes in Net Assets", last NINE years FY2002–FY2010) | 277–280 | 273–274 / 275–276 | 281–282 / 283 | 284 | 287–288 | 289–290 | 291 / 292 | 295 | 297 | 299–300 | 301–304 | 305–306 |

Each horizontal table is two "halves" of two pages each: the first page carries the row labels and 3–4 year columns, the
following page carries only numbers for the remaining years, printed on exactly the same baseline (y) as the labels.
Vertical tables (fiscal year down the left) use a continuation page for the right-hand columns, again on the same baselines.

## Parsing approach

* Everything is rebuilt from word coordinates (`page.get_text("words")`), never from raw text order: words are clustered into
  rows by y (2.6 pt), rows are read left-to-right, and a parenthesis PyMuPDF split off (`(` + `2,746,904)`) is re-attached.
* Horizontal tables: the year header row is located (≥2 four-digit years, with any `(n)` footnote flag next to a year),
  every numeric token to its right is assigned to the nearest year column by right edge, duplicate hits drop `-` placeholders.
  The label page defines rows (label, indent, y); label-less continuation pages are joined to those rows by y (±3.5 pt).
  Section paths come from the indentation of label-only rows, with block headers (Expenses, Program Revenues, Revenues,
  Expenditures…) and peer blocks (Governmental / Business-type / Internal service activities) handled explicitly; wrapped
  two-line labels are merged ("Compensation for loss, sale or" + "damage to property"; "Average daily actual water pumped"
  + "(millions of gallons per day)").
* Vertical tables: rows start with `2015-16` (→ FY2016) or a calendar year; column names are supplied per page in
  `extract_acfr.py` and the token count is checked against them for every row.
* Footnotes: `(n)` text blocks below each table are captured; flags on a year header, on a line label or at the end of a
  data row are resolved to that text in the `footnote` column.
* Zero parser warnings across all 12 reports; label-page row counts are identical for every year column of every table.

## Validation results (see `validation_report.txt`)

* Table 1 (changes in net position): 1,547 additive / cross-foot checks over 12 reports × 10 years (function lines =
  total governmental, business-type lines = total, program revenue lines = totals, gov + bt = primary government,
  program revenue − expenses = net (expense) revenue, net (expense) + general revenues = change in net position):
  **0 failures** (tolerance 1 thousand). One parse defect was found and fixed on the way (a split parenthesis on
  ACFR_FY2024 p316 that made the FY2024 net expense positive).
* Table 2 (changes in fund balances): 600 checks (revenues = total, all expenditure lines = total, revenues − expenditures
  = excess, other financing = total, excess + other financing = net change): **0 failures** (tolerance $1).
* Other tables: FTE 200 checks, fund balances 120, property tax 180, debt 120 — **one failure, which is in the report
  itself**: ACFR_FY2025 p325–326, Fund Balances of Budgeted Governmental Funds, FY2025 General Purpose School Fund
  subtotal is printed as 205,462,834 while its components (2,026,942 + 203,735,892) sum to 205,762,834; the grand total
  744,816,594 is consistent with the component sum, so the printed subtotal is a $300,000 typo. Values are kept as printed.
* Spot checks: 5 random values per table (40 in all, seed 7, `spot_check.py`) were printed next to the raw PDF line and
  eyeballed; all 40 tokens were found on the recorded page in the expected column position.
* Coverage: every table covers FY2001–FY2025 (changes in net position FY2002–FY2025, because the FY2010 CAFR shows "last nine
  fiscal years" — government-wide reporting began with GASB 34 in FY2002) and demographics CY2000–CY2024, with no gaps.

## Caveats that matter for a spending-growth analysis

**Accounting breaks that were NOT restated (level shifts inside the series)**
* FY2015 — GASB 68 (pension liability/expense). Footnote in every FY2015–FY2023 report: "Amounts for prior years have not
  been restated." Expense by function from FY2015 on includes actuarially determined pension expense; FY2014 and earlier do
  not. General government jumps 134,592 → 188,330 (+40%) between FY2014 and FY2015; this also coincides with the July 1 2014
  move of General Services internal-service programs into general government (FTE footnote).
* FY2018 — GASB 75 (OPEB). Same "not restated" footnote in FY2018–FY2024. The FY2025 ACFR footnote (2) text layer reads
  "...have been restated", but a line of that footnote is missing from the PDF text and the FY2016–FY2017 values printed in
  the FY2025 report are identical to those in the FY2017 and FY2018 reports, so nothing was restated.
* FY2022 — the Government changed retiree OPEB benefits, "which reduced expenses for various postemployment benefits.
  Amounts for prior years have not been restated" (flag (3) on the 2022 column). FY2022 governmental expenses by function are
  therefore depressed relative to FY2021 and FY2023 (e.g. Fiscal administration 5,135 vs 46,251 / 39,152).
* FY2003 — net assets restated for net pension assets and a utility-district acquisition; prior years not restated (FY2010 CAFR).
* Changes in fund balances are modified-accrual and unaffected by GASB 68/75; they are the cleaner series for cash-basis
  spending growth, but they include capital outlay and debt service and exclude the component units.

**Restatements actually found between reports (`restatements.csv`, 412 cells)**
* FY2006–FY2010 government-wide: the FY2015 CAFR (and all later) restate "Interest and other debt related costs" (e.g. FY2010
  76,553 → 80,460), Water & Sewer and District Energy System expenses, and therefore every dependent total, versus the FY2010
  CAFR. Function lines other than interest are unchanged. Interest was also restated downward in FY2008–FY2009.
* FY2006–FY2010 debt: the FY2015 CAFR reports general obligation debt ~3.8% higher than the FY2010 CAFR for the same years
  (e.g. FY2006 1,600,695 → 1,661,934 thousand) and per-capita/percent ratios move with it — a change in what is counted
  (premiums/discounts), not new borrowing. Prefer the later report for a consistent series.
* FY2006–FY2010 FTE: Education FTEs restated upward ~9% (FY2006 8,382 → 9,136) and Public works FY2010 263 → 363 in the FY2015
  CAFR; the FY2015 report's series is internally consistent FY2006–FY2015.
* Property tax: collections-to-date, subsequent-year collections and outstanding delinquent taxes for FY2006–FY2010 are
  updated in later reports (normal roll-forward, not errors); USD realty assessed value FY2007–FY2010 revised −0.4%.
* Changes in fund balances: the debt-service ratio is printed to two decimals through the FY2021 ACFR and to whole percents
  from FY2022; the FY2022 ACFR folds "Debt issue costs" into "Fiscal charges" for FY2013 (3,716,622 → 6,421,271), other
  reports keep the two lines. Values of all other lines agree across every pair of reports.
* Operating indicators: State fair attendance FY2006–FY2010, Public Works tons of disposed waste FY2006–FY2012 and Library
  visits FY2018 differ between reports; capital assets: parks number/acreage/greenways FY2015 differ FY2015 vs FY2024 report.

**Reclassifications and renamed lines (`line_presence_differences.csv`)**
* "Public works, highways and streets" is renamed "Transportation, highways and streets" in the FY2025 ACFR (all three tables);
  the validation script treats them as the same line. Same for "Changes in Net Assets" (FY2010) vs "Net Position".
* Business-type activities move in and out of the primary government: Nashville Convention Center (operations ceased 2017
  after the Music City Center — a component unit, the Convention Center Authority — opened May 2013; its employees moved to
  the Authority); Police Secondary Employment and Community Education Commission moved into the general fund (July 2014 and
  July 2017; non-zero FY2002–FY2014 and FY2010–FY2016 respectively), School Community Education existed FY2006–FY2010;
  Stormwater Operations is non-zero from FY2010, District Energy System and Surplus Property Auction from FY2003, Municipal
  Auditorium and Police Impound from FY2006 (earlier years print "-"). Business-type totals are therefore not comparable
  across the whole span.
* Hospital Authority: removed from the enterprise funds in FY2000 and reported as a component unit; "Public health and
  hospitals" from then on includes the operating subsidy to the Authority, with one-time spikes of $50 million (FY2006) and a
  $32 million debt forgiveness (FY2010). Sports Authority became a component unit in FY2001 (stadium costs sat in
  Recreational and cultural before that). Component units are outside every table here except the Music City Center
  operating-indicator line.
* Internal service activities (FTE) were progressively moved into general government (2009, July 2014) — governmental FTE
  totals rise for that reason as well as hiring.
* Changes in fund balances: "Bond issue costs" (FY2010 CAFR) becomes "Debt issue costs" later; "Arbitrage rebate", commercial
  paper, swaption, "Distribution of net assets" lines exist only in older reports (all zero where absent); "Leases" and
  "Subscriptions" (GASB 87/96) appear from the FY2024 ACFR.
* Property tax rates: reappraisal years (2001, 2005, 2009, 2013, 2017, 2021, 2025) reset the certified rate; Council
  reallocations among funds are flagged (2) (3) (4) in the `footnote` column. FY2021 rate increase by Council.
* Demographics: the FY2024 and FY2025 ACFRs head the income column "Per Household Personal Income" while FY2010–FY2020 say
  "Per Capita"; the figures are the same BEA per-capita series (identical overlapping values), so the line is called
  `Per capita personal income` throughout. From CY2022 all figures come from BEA BEARFACTS; earlier from Census/Commerce.
  Latest-year income is N/A in every report; population for the latest year is a prior-year carry-forward in FY2025 (CY2024
  715,884 = CY2021). FY2010's CY2000–CY2009 and FY2015's CY2005–CY2014 values agree exactly.
* COVID-19 (FY2020–FY2023) distorts activity-based revenues and operating indicators (footnotes retained).
* FY2025's budgeted-fund-balance subtotal typo noted above.
