Repository navigation
feat: fiscal-year periods and survey-year helpers (#77, R side) - #4
Conversation
…it (#77) data-raw/measure_fiscal_year_end.R reads a corpus's long partitions and reports, by survey year and government type, how many government-years have a missing, zero, implausible or internally conflicting fiscal_year_end; the most common values; how often a government's value changes between consecutive years; and every state government's and the District of Columbia's value. On the bundled fixture (FY2011, FY2012, FY2019, FY2020; full published partitions from the 2026-08-03 build) 0.1%-0.9% of government-years are missing a value, none is zero, implausible or conflicting, and every state government keeps the same value in all four years. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qbe6u2h83wgZdTgJgE4Xh5
|
Thanks for this — and one thing worth knowing before it happens. This repository is a mirror. Development happens on Gitea at Because that merge preserves your commits at their original SHAs, GitHub will
If it is not going to be merged, you will get an actual reply saying so. Substantial contributions get a Full details: CONTRIBUTING.md. |
`year` is the Census survey year, and Census files a government's fiscal year under survey year Y when it ended between July 1 of Y-1 and June 30 of Y, so one survey year covers different months for different governments. cog_spending(), cog_revenue() and cog_balances() gain a trailing `fiscal_period = FALSE`. With TRUE, every row gains fiscal_year_end (MMDD integer), period_start and period_end (Dates, inclusive), looked up per government-year from long.fiscal_year_end so a change of fiscal year is respected, plus provenance$transformations$fiscal_period. With the default, columns and provenance are exactly as before. cog_fiscal_periods(govid, years) returns the govid x years grid of periods; cog_survey_year(govid, date) returns the survey year whose period contains a date, using each candidate year's own fiscal_year_end and returning NA rather than borrowing another year's value. State governments, and the District of Columbia, cover the fiscal year ending in calendar year Y. That changes Alabama, Michigan (September 30) and Texas (August 31). Census's 2004 and 2006 technical documentation lists those exceptions, and the corpus agrees for survey year 2020: those states' federal aid rises with the CARES Act in 2020 while New York's and 15 large September-30 local governments' rises in 2021. D.C. rests on the documentation alone. Tests run against the bundled fixture (85 expectations). Refs #77 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qbe6u2h83wgZdTgJgE4Xh5
NEWS.md gains a development-version entry for fiscal_period, cog_fiscal_periods() and cog_survey_year(). total-spending.Rmd shows that its Florida rollup mixes a June 30 state (July 2019 to June 2020) with two September 30 counties (October 2018 to September 2019) under the same 2020. coverage-counters.Rmd counts the FY2012 fiscal year ends of Georgia cities (273 December 31, 196 June 30, 36 September 30) and what months they cover. population-denominators.Rmd notes that each cohort year is a survey year. The first two chunks run against the bundled fixture. Refs #77 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qbe6u2h83wgZdTgJgE4Xh5
Gitea issue #77 (R side). Step 4, cog-api, is out of scope, so the commits say
Refs #77rather thanCloses #77.Summary
yearis the Census survey year, which covers different calendar months for different governments. This PR does three things:long.fiscal_year_endis (step 1, results below). That came before anything was built on it; the draft PR carried those results alone.fiscal_period = FALSEargument (step 2).cog_fiscal_periods()andcog_survey_year()(step 3), plus docs (step 5).Step 1: how usable is
fiscal_year_end?What I measured: the bundled fixture's long partitions, FY2011, FY2012, FY2019 and FY2020, read directly with DuckDB.
data-raw/regenerate_fixture_corpus.Rcopies each partition byte-for-byte from the publish tree (build 2026-08-03, schema 6), so these are full published years for types 0–3. I could not reach any other year. The corpus parquet files redirect tous.aws.cdn.hf.co, which the sandbox's network policy blocks, and the public API does not exposefiscal_year_end. Nothing below describes FY1967–FY2010, FY2013–FY2018 or FY2021+.Reproduce with
Rscript data-raw/measure_fiscal_year_end.R(commit 533b80d).1231,630and930cover 84% to 95% of government-years per year. Then430,331,228and531.1231↔630. That is also where the source switches from the legacy to the modern files, and I can't tell real changes from artifacts.630in all four years. Alabama and Michigan are930, Texas831, New York331.930in all four years.Conclusion: coverage in these four years supports steps 2 and 3. Government-years with no usable value get
NAperiods. No other year is assumed to look the same.Open questions
Does the same rule hold for state governments (type 0)? No, for the three states whose fiscal year ends after June 30. For them, survey year Y is the fiscal year ending in calendar year Y.
Census documentation.
Data test, survey year 2020 (public API, build 2026-10-26). CARES Act relief reached governments in April 2020. New York (March 31) is a control: its survey-year 2020 is the fiscal year ending March 31, 2020 under either reading, before most of the aid arrived.
Under the plain rule, Alabama's and Michigan's survey-year 2020 would end September 30, 2019 and Texas's August 31, 2019. Neither period contains April 2020, so their jump would land in 2021, as New York's does. It lands in 2020 instead, with the June-30 states.
Do the older exceptions still apply, and do any reach types 0–3?
Ordinary local governments with a September 30 year end follow the plain rule. Across 15 large
930cities and counties (San Antonio, Dallas, Austin, Fort Worth, Jacksonville; Miami-Dade, Broward, Palm Beach, Hillsborough, Orange FL, Pinellas, Bexar, Tarrant, Dallas County, Travis), median IG Federal growth is +6.2% in survey-year 2020 and +39.1% in 2021. Six of the 15 exceed +50% in 2021, against two in 2020.What changed
Steps 2 and 3,
R/fiscal.R(new):.survey_period()implements the rule:NA..fiscal_year_lookup()readsfiscal_year_endper government-year fromlong. A government-year whose rows disagree getsNA, which never happens in the fixture.cog_spending(),cog_revenue(),cog_balances()each gain a trailingfiscal_period = FALSE. WithTRUE, every row gainsfiscal_year_end,period_startandperiod_end, plusprovenance$transformations$fiscal_period. For holdings,period_endis the balance date.cog_fiscal_periods(govid, years): the govid × years grid offiscal_year_end,period_startandperiod_end,NAwhere unknown.cog_survey_year(govid, date): the survey year whose period contains each date. It tries Y, Y+1 and Y+2 with each candidate year's ownfiscal_year_end, returnsNArather than borrowing another year's value, and takes the earlier year on overlap.NAMESPACE,man/, and_pkgdown.yml(new "Fiscal years" reference section).Step 5, docs:
?cog_fiscal_periods, inherited by?cog_survey_year, with a worked example for survey year 2017 and the state and D.C. exception.total-spending.Rmd(evaluated chunk): the Florida rollup mixes a June-30 state (July 2019–June 2020) with two September-30 counties (October 2018–September 2019) under the same 2020.coverage-counters.Rmd(evaluated chunk): FY2012 year ends of the 566 Georgia cities: 273 December 31, 196 June 30, 36 September 30, small groups, and 31 with no value.population-denominators.Rmd: a note on survey years. The file iseval = FALSE.NEWS.md: a new# uscogdata (development version)entry.Shape changes
fiscal_periodunset, all three verbs return the same columns and provenance as before. A test checks the names and the absence of the provenance block.cog_spending(),cog_revenue()andcog_balances()each gain one trailing argument,fiscal_period = FALSE. Positional calls are unaffected, and cog-api can feature-detect it withformals(), as withlimit.fiscal_period = TRUE:fiscal_year_end(integer),period_start(Date),period_end(Date).provenance$transformations$fiscal_periodis added.provenance-v1.jsonallows additional properties.cog_geographic_rollup()andcog_peer_compare()do not takefiscal_period.cog_fiscal_periods()andcog_survey_year().# uscogdata (development version)heading toNEWS.md. Whichever lands second has a one-line conflict at the top of the file.Tests
tests/testthat/test-fiscal-period.R: 85 expectations, all against the bundled fixture or synthetic data:longtableTRUEper_capita,adjust_to_year,limitandcompletemaingives 1,108.R CMD build --no-manual+R CMD check --no-manual: all three vignettes build and run, and tests pass. Status is 1 WARNING and 2 NOTEs, the same as onmain:en_US.UTF-8locale..roborev.tomlis a hidden file.extensions.duckdb.org, so local runs dropcog_open()'sINSTALL httpfs; LOAD httpfs;line in a scratch copy. That is not in any commit.RoxygenNote, soDESCRIPTIONis untouched.Verified
Not verified
data_year < year, a schema 7 column that the fixture lacks. Their periods describe the survey year, not the year the data pertain to. The docs say so, but nothing adjusts for it.🤖 Generated with Claude Code
https://claude.ai/code/session_01Qbe6u2h83wgZdTgJgE4Xh5