Skip to content

docs: add a vignette on reading provenance$coverage (#72) - #2

Merged
jknowles merged 2 commits into
mainfrom
claude/great-knuth-4jky3n-issue-72
Nov 4, 2026
Merged

jknowles merged 2 commits into
mainfrom
claude/great-knuth-4jky3n-issue-72

Conversation

@jknowles

@jknowles jknowles commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Gitea issue #72

What changed

  • New vignettes/coverage-counters.Rmd. It covers:
    • the five columns of provenance$coverage
    • what each counter counts, per .coverage_table(), R/rollup.R and R/peers.R
    • the three groups the counters split the named governments into
    • the two ratios, with reporting / expected shown as their product
    • comparing a census year with a sample year
    • the FY2022 Georgia example
    • peer comparisons counting peers only
    • how coverage = "census", coverage = "consistent" and per_capita = TRUE change the counters
    • is_census_year, and a summary
  • _pkgdown.yml: coverage-counters added to the "Concepts" articles index.

Definitions I took from the code, not from the counter names:

  • n_units_collected comes from the spending long view: spending_long_harmonized, or spending_long under basis = "raw". That view holds every non-aggregate, non-intergovernmental expenditure row. The vignette demonstrates the definition by rebuilding the counts from cog_spending(..., category = "All Categories", expenditure_concept = "direct").
  • In cog_peer_compare(), n_units_expected is length(peer_govids) and n_units_reporting counts peer rows only, so the target appears in none of the three counters.
  • In cog_geographic_rollup(), the coverage = "consistent" filter and the per_capita = TRUE row drop both run before n_units_reporting is counted. Neither touches n_units_expected or n_units_collected.

Census year vs sample year: resolved against the published corpus

The draft version of this PR asked which was right: this vignette, or the "Reading coverage" sections of R/peers.R and R/rollup.R. Those sections say the valid comparison is "the same category across a census year … and a sample year, where the real-zero component is roughly constant." I checked the published corpus (build of 2026-10-26) through the public API.

Police, all US cities Census years (FY2012, FY2017, FY2022) Sample years (FY2013–FY2023)
Participation among collected cities 0.70, 0.73, 0.72 0.93 to 0.95
Collected, no Police rows 5,745, 5,274, 5,298 187 to 287

Among the 3,867 cities collected in both FY2022 and FY2021, the gap disappears:

All collected, FY2022 All collected, FY2021 Same cities, FY2022 Same cities, FY2021
Police 0.722 0.934 0.929 0.935
Fire 0.621 0.807 0.800 0.807
Libraries 0.292 0.455 0.453 0.455
Housing & Community 0.199 0.440 0.449 0.440

FY2022 against FY2023 gives the same result. Georgia cities alone, FY2007–FY2023: participation is 0.72 to 0.75 in every census year and 0.93 to 1.00 in every sample year.

The collected-but-no-rows group is not constant between a census year and a sample year. Sample years collect a different, larger set of cities. The vignette (commit e3cb9d5) therefore recommends comparing census years with each other, or the same governments across years. It also adds a fixture chunk that does the second: 99 Georgia cities collected in both FY2012 and FY2019, with participation 0.97 and 0.94.

The roxygen in R/peers.R and R/rollup.R still says the opposite. That fix is outside #72 and is not in this PR.

How it was built and tested

Locally, on Ubuntu 24.04 with R 4.3.3 and duckdb 2.0.0 (compiled from CRAN source). The sandbox could not reach extensions.duckdb.org, so I built and checked on a scratch copy with cog_open()'s INSTALL httpfs; LOAD httpfs; line removed. The fixture is a local path and never uses httpfs. That patch is not in any commit.

First commit (4bfb6eb):

  • R CMD build --no-manual then R CMD check --no-manual: the vignette builds, and its code runs. Tests pass.
  • Check status was 1 WARNING and 2 NOTEs, all pre-existing or environmental:
    • WARNING: the sandbox has no en_US.UTF-8 locale.
    • NOTE: .roborev.toml is a hidden file in the tarball.
    • NOTE: installed size, mostly the fixture.
  • pkgdown::check_pkgdown(): no problems.
  • CI passed on macOS, Windows, Ubuntu release and Ubuntu devel.

Second commit (e3cb9d5):

  • Rendered with rmarkdown::html_vignette().
  • R CMD build --no-manual rebuilt all vignettes ("creating vignettes ... OK").
  • I did not run the full R CMD check locally again. CI runs it on this push.

Fixture caveat: every evaluated chunk runs against the fixture. The vignette states what data-raw/regenerate_fixture_corpus.R does: each fixture year is a full copy of the published partition, from the 2026-08-03 build. The fixture's FY2012 and FY2019 Georgia Police counts (534/398 and 103/96) match the published corpus. Its crosswalk lists 566 Georgia cities, where the published corpus lists 567. The FY2022 chunk is eval = FALSE with a "Not run" comment, following population-denominators.Rmd.

Checked against output:

  • Every count, ratio and median in the prose was checked against rendered fixture output.
  • Every published-corpus figure was checked against the API responses: FY2022 Georgia (567 expected, 535 collected, 393 reporting; 32 and 142), and the national census/sample and same-city participation figures above.

Still not verified

  1. Contracting example. "A city that contracts its policing to the county sheriff lands here for category = "Police". Its Police spending is a real zero." This illustrates the mechanism using the reference pages' example. I did not check any specific city.
  2. Survey design. "The Census of Governments collects from every government only in years ending in 2 or 7 and from a sample in other years." This comes from R/coverage.R and the reference pages.
  3. Code-only behavior. The per_capita = TRUE sentences and the sentence about cog_peer_compare() exempting the target from "consistent" are read from the code. No chunk shows them.
  4. Fitzgerald peer example. It is shown on the fixture only and was not checked against the published corpus.

Where the example comes from: the task description called this "the FY2012 Georgia Police example already in the roxygen and README". The roxygen gives FY2022 (393 of 567), and README.md has no Georgia Police example.

Noticed, not changed

  • Roxygen conflict. R/peers.R and R/rollup.R say a census year vs a sample year is the valid comparison. The published corpus contradicts this (see above). It needs a follow-up issue.
  • duckdb storage message. duckdb 2.0.0 prints "duckdb keeps downloaded extensions and secrets in a temporary directory" on the first connection of a session. It appears in the rendered output of every vignette that opens one.
  • Missing vignette. cog_find_peers() and cog_gov_search() point users at vignette('coverage-scope'), which does not exist.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Qbe6u2h83wgZdTgJgE4Xh5

vignettes/coverage-counters.Rmd explains the three per-year counters that
cog_geographic_rollup() and cog_peer_compare() attach as
provenance$coverage, using the definitions in .coverage_table(),
R/rollup.R and R/peers.R: n_units_expected (the ids passed, or the peers),
n_units_collected (of those, how many have any row in the spending long
view that year) and n_units_reporting (of those, how many have a row in
the requested category). It splits the named governments into three
groups, defines the collection rate and category participation, and
shows that reporting / expected is their product.

The evaluated chunks run against the bundled fixture and say so: Georgia
cities and Police across FY2011, FY2012, FY2019 and FY2020, a peer
comparison, and the census, consistent and per_capita effects. The FY2022
example from the reference pages needs the published corpus and is not
evaluated, following population-denominators.Rmd.

The article is added to the pkgdown Concepts index.

Closes #72

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qbe6u2h83wgZdTgJgE4Xh5
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown

Thanks for this — and one thing worth knowing before it happens.

This repository is a mirror. Development happens on Gitea at
gitea.civilytics.org/Civilytics/uscogdata. Your pull request will be fetched
from here, landed there, and synced back.

Because that merge preserves your commits at their original SHAs, GitHub will
mark this pull request "Merged" on its own
— without anyone visibly clicking
the Merge button, and possibly without a review comment on this page first.

If your pull request closes as "Merged" and nobody appears to have merged it,
that is the normal, successful outcome — not a rejection.

If it is not going to be merged, you will get an actual reply saying so.

Substantial contributions get a ctb entry in DESCRIPTION, which surfaces in
citation("uscogdata"). There is no CLA and no DCO sign-off.

Full details: CONTRIBUTING.md.

Checked against the published corpus (build of 2026-10-26) through the
public API:

- FY2022 Georgia cities, Police: 567 expected, 535 collected, 393
  reporting. The 174-city gap is 32 not collected and 142 collected with
  no Police rows. The FY2022 section now states the split.
- All US cities: Police participation among collected cities is 0.70,
  0.73 and 0.72 in FY2012, FY2017 and FY2022, and 0.93 to 0.95 in every
  sample year FY2013-FY2023. Among the 3,867 cities collected in both
  FY2022 and FY2021 it is 0.929 and 0.935; Fire, Libraries and Housing &
  Community move by 0.01 or less on the same cities.

A census year and a sample year collect different sets of governments,
so the census-vs-sample section now recommends comparing census years
with each other, or the same governments across years, and adds a
fixture chunk that measures participation over the 99 Georgia cities
collected in both FY2012 and FY2019 (0.97 and 0.94).

The fixture caveat now says what data-raw/regenerate_fixture_corpus.R
does: each fixture year is a full copy of the published partition. Its
FY2012 and FY2019 Georgia Police counts match the published corpus; the
newer crosswalk lists 567 Georgia cities where the fixture lists 566.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qbe6u2h83wgZdTgJgE4Xh5
@jknowles
jknowles marked this pull request as ready for review November 4, 2026 15:51
@jknowles
jknowles merged commit 077fe5f into main Nov 4, 2026
3 of 4 checks passed
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.

2 participants