diff --git a/DESCRIPTION b/DESCRIPTION index ec395ac..ac50400 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -37,6 +37,7 @@ Suggests: ggplot2 Config/testthat/edition: 3 VignetteBuilder: knitr +Roxygen: list(markdown = TRUE) RoxygenNote: 7.3.3 MinCorpusSchema: 4 MaxCorpusSchema: 7 diff --git a/R/balance_caveats.R b/R/balance_caveats.R index dc25401..593ad0a 100644 --- a/R/balance_caveats.R +++ b/R/balance_caveats.R @@ -53,7 +53,7 @@ ) } -#' Per-subtype [min year, max year] extents for EVERY balance subtype in the +#' Per-subtype \[min year, max year\] extents for EVERY balance subtype in the #' mounted corpus, memoised for the session. #' #' The query carries no govid and no year predicate -- its answer is a property diff --git a/man/cog_balances.Rd b/man/cog_balances.Rd index eb56bed..6384a34 100644 --- a/man/cog_balances.Rd +++ b/man/cog_balances.Rd @@ -21,109 +21,109 @@ cog_balances( } \arguments{ \item{govid}{Canonical govid(s): a character vector, or a data frame with a -`canonical_govid` column (e.g. from [cog_gov_search()]). `NULL` to name -the cohort by `state`/`type` instead.} +\code{canonical_govid} column (e.g. from \code{\link[=cog_gov_search]{cog_gov_search()}}). \code{NULL} to name +the cohort by \code{state}/\code{type} instead.} \item{years}{Integer vector of fiscal years.} \item{category}{Optional character vector of categories to keep. One of -`"Fund Balances"`, `"Insurance Trust Balances"`, -`"Retirement System Holdings"`. There is deliberately no `subtype` -argument: for holdings, `category` is a strict coarsening of -`balance_subtype` (unlike the money verbs, where the two axes cross), so +\code{"Fund Balances"}, \code{"Insurance Trust Balances"}, +\code{"Retirement System Holdings"}. There is deliberately no \code{subtype} +argument: for holdings, \code{category} is a strict coarsening of +\code{balance_subtype} (unlike the money verbs, where the two axes cross), so every combination would be either redundant or empty. -`category = "Fund Balances"` is exactly the `general` family -(`W01`/`W31`/`W61`). `balance_subtype` is returned, so a finer split is -one `dplyr::filter()` away. The reserved pseudo-category -`"All Categories"` (see [cog_spending()]) is **not** supported here and -errors with class `uscogdata_all_categories_unsupported`: it sums a +\code{category = "Fund Balances"} is exactly the \code{general} family +(\code{W01}/\code{W31}/\code{W61}). \code{balance_subtype} is returned, so a finer split is +one \code{dplyr::filter()} away. The reserved pseudo-category +\code{"All Categories"} (see \code{\link[=cog_spending]{cog_spending()}}) is \strong{not} supported here and +errors with class \code{uscogdata_all_categories_unsupported}: it sums a concept's subtype scope, and holdings are a stock with no concept -vocabulary to sum across. Omit `category` to get every category broken +vocabulary to sum across. Omit \code{category} to get every category broken out instead.} -\item{per_capita}{Divide holdings by population. Note this is a **stock per -resident** (reserves per person), which is *not* comparable to -[cog_spending()]'s per-capita figures -- those are a flow per person.} +\item{per_capita}{Divide holdings by population. Note this is a \strong{stock per +resident} (reserves per person), which is \emph{not} comparable to +\code{\link[=cog_spending]{cog_spending()}}'s per-capita figures -- those are a flow per person.} \item{adjust_to_year}{Deflate to this year's dollars (CPI-U).} \item{basis}{Accepted for uniformity with the money verbs, but currently a -**no-op**: `harmonization_map` carries no balance-code rows, so harmonized +\strong{no-op}: \code{harmonization_map} carries no balance-code rows, so harmonized and raw space are identical for holdings. Reported in -`provenance$basis_note`.} +\code{provenance$basis_note}.} -\item{recipe}{Optional harmonization recipe id (see [cog_recipes()]). -`"cash_securities_z77_wide"` and `"cash_securities_z78_wide"` bridge the +\item{recipe}{Optional harmonization recipe id (see \code{\link[=cog_recipes]{cog_recipes()}}). +\code{"cash_securities_z77_wide"} and \code{"cash_securities_z78_wide"} bridge the wide era to the modern one.} -\item{state, type}{Name the cohort by predicate instead of by id: `state` is - a 2-letter USPS abbreviation (or a FIPS code) and `type` is one of - `"state"`, `"county"`, `"city"`, `"township"` (or the integer `0:3`) -- - the same vocabulary, and the same internal coercion, as - [cog_gov_search()]. Both default to `NULL`. - - The cohort is then expressed as a subquery against `canonical_fips_xwalk` - inside each statement rather than round-tripped through R as a literal id - list. For a fleet-scale cohort that is the difference between a - 301,591-character `IN` list re-parsed in 5--8 statements per call and a - constant-size predicate: measured at **94 ms versus 449 ms** for the same - FY2022 aggregate over the 20,106-government `type = "city"` cohort, within - 7% of the no-filter floor. - - Supplying `govid` **and** `state`/`type` INTERSECTS them -- the - governments in `govid` that also match the predicate -- rather than one - silently taking precedence. Naming no cohort at all (`govid`, `state` and - `type` all `NULL`) aborts with class `uscogdata_no_cohort`. - - When the cohort is named by predicate, `provenance$scope$govids_found` - and `govids_missing` are empty -- there is no id list to report against -- - and `provenance$scope$cohort` carries `state`, `type` and - `n_governments` instead. A `govid`-named cohort reports exactly as before.} +\item{state, type}{Name the cohort by predicate instead of by id: \code{state} is +a 2-letter USPS abbreviation (or a FIPS code) and \code{type} is one of +\code{"state"}, \code{"county"}, \code{"city"}, \code{"township"} (or the integer \code{0:3}) -- +the same vocabulary, and the same internal coercion, as +\code{\link[=cog_gov_search]{cog_gov_search()}}. Both default to \code{NULL}. + +The cohort is then expressed as a subquery against \code{canonical_fips_xwalk} +inside each statement rather than round-tripped through R as a literal id +list. For a fleet-scale cohort that is the difference between a +301,591-character \code{IN} list re-parsed in 5--8 statements per call and a +constant-size predicate: measured at \strong{94 ms versus 449 ms} for the same +FY2022 aggregate over the 20,106-government \code{type = "city"} cohort, within +7\% of the no-filter floor. + +Supplying \code{govid} \strong{and} \code{state}/\code{type} INTERSECTS them -- the +governments in \code{govid} that also match the predicate -- rather than one +silently taking precedence. Naming no cohort at all (\code{govid}, \code{state} and +\code{type} all \code{NULL}) aborts with class \code{uscogdata_no_cohort}. + +When the cohort is named by predicate, \code{provenance$scope$govids_found} +and \code{govids_missing} are empty -- there is no id list to report against -- +and \code{provenance$scope$cohort} carries \code{state}, \code{type} and +\code{n_governments} instead. A \code{govid}-named cohort reports exactly as before.} \item{limit}{Maximum number of result rows to return, pushed into the SQL -rather than applied after materializing every row. `NULL` (default) -returns everything. Cannot be combined with `recipe` -- see `offset` and -`total_rows`.} - -\item{offset}{Rows to skip before `limit` starts counting (0-based). -Ignored if `limit` is `NULL`; defaults to `0L` when `limit` is set.} - -\item{fiscal_period}{If `TRUE`, add `fiscal_year_end`, `period_start` and -`period_end` to every row, as [cog_spending()] does. Holdings are a stock -measured at the end of the fiscal year, so `period_end` is the date the -balance describes and `period_start` is the start of that fiscal year. -Defaults to `FALSE`, which leaves the result unchanged.} +rather than applied after materializing every row. \code{NULL} (default) +returns everything. Cannot be combined with \code{recipe} -- see \code{offset} and +\code{total_rows}.} + +\item{offset}{Rows to skip before \code{limit} starts counting (0-based). +Ignored if \code{limit} is \code{NULL}; defaults to \code{0L} when \code{limit} is set.} + +\item{fiscal_period}{If \code{TRUE}, add \code{fiscal_year_end}, \code{period_start} and +\code{period_end} to every row, as \code{\link[=cog_spending]{cog_spending()}} does. Holdings are a stock +measured at the end of the fiscal year, so \code{period_end} is the date the +balance describes and \code{period_start} is the start of that fiscal year. +Defaults to \code{FALSE}, which leaves the result unchanged.} } \value{ -Tibble with columns `year`, `canonical_govid`, `gov_name`, - `balance_subtype`, `category`, `amt_nominal`, `codes_included`, - `aggregate_fallback`, plus optional `amt_per_capita_nominal` and - `pop_source` (when `per_capita = TRUE`), optional `amt_real` (when - `adjust_to_year` is set), and optional `amt_per_capita_real` (only when - **both** `per_capita = TRUE` and `adjust_to_year` are set -- there is no - nominal per-capita column to deflate otherwise), and `fiscal_year_end`, - `period_start` and `period_end` when `fiscal_period = TRUE`. Amounts are - full US dollars. - - Carries a `provenance` attribute matching - `inst/schemas/provenance-v1.json`, whose `balance_caveats` block reports - `not_gaap`, `not_gaap_note`, `coverage_window` (measured year extents for - every balance subtype in the mounted corpus, not only the observed ones) - and `truncated` (the observed subtypes whose coverage falls short of the - requested years). `expenditure_concept`/`revenue_concept` are `NA` -- - holdings are a stock, not a flow, so neither concept vocabulary applies. - - When `limit` is set, also carries a `total_rows` attribute: the full - unpaginated row count, computed by the same query (`COUNT(*) OVER()`) - rather than a second scan. +Tibble with columns \code{year}, \code{canonical_govid}, \code{gov_name}, +\code{balance_subtype}, \code{category}, \code{amt_nominal}, \code{codes_included}, +\code{aggregate_fallback}, plus optional \code{amt_per_capita_nominal} and +\code{pop_source} (when \code{per_capita = TRUE}), optional \code{amt_real} (when +\code{adjust_to_year} is set), and optional \code{amt_per_capita_real} (only when +\strong{both} \code{per_capita = TRUE} and \code{adjust_to_year} are set -- there is no +nominal per-capita column to deflate otherwise), and \code{fiscal_year_end}, +\code{period_start} and \code{period_end} when \code{fiscal_period = TRUE}. Amounts are +full US dollars. + +Carries a \code{provenance} attribute matching +\code{inst/schemas/provenance-v1.json}, whose \code{balance_caveats} block reports +\code{not_gaap}, \code{not_gaap_note}, \code{coverage_window} (measured year extents for +every balance subtype in the mounted corpus, not only the observed ones) +and \code{truncated} (the observed subtypes whose coverage falls short of the +requested years). \code{expenditure_concept}/\code{revenue_concept} are \code{NA} -- +holdings are a stock, not a flow, so neither concept vocabulary applies. + +When \code{limit} is set, also carries a \code{total_rows} attribute: the full +unpaginated row count, computed by the same query (\verb{COUNT(*) OVER()}) +rather than a second scan. } \description{ -Returns Census cash-and-security holdings (`category_type = "balance"`): +Returns Census cash-and-security holdings (\code{category_type = "balance"}): fund balances, retirement system holdings and insurance trust balances. } \section{Holdings are not GAAP fund balance}{ -Census holdings are **gross** -- no liabilities are netted -- so a reserve +Census holdings are \strong{gross} -- no liabilities are netted -- so a reserve ratio built from them overstates what is actually available. They are not comparable to a GAAP fund balance from an ACFR. } diff --git a/man/cog_basket_resolution.Rd b/man/cog_basket_resolution.Rd index 3c1825f..1fca3f0 100644 --- a/man/cog_basket_resolution.Rd +++ b/man/cog_basket_resolution.Rd @@ -7,21 +7,21 @@ cog_basket_resolution(x, expand_candidates = FALSE) } \arguments{ -\item{x}{A tibble returned by basket-mode [cog_gov_search()].} +\item{x}{A tibble returned by basket-mode \code{\link[=cog_gov_search]{cog_gov_search()}}.} -\item{expand_candidates}{Logical. If `TRUE`, keeps the `candidates` +\item{expand_candidates}{Logical. If \code{TRUE}, keeps the \code{candidates} list-column (full-schema match candidates per input row). Default -`FALSE`.} +\code{FALSE}.} } \value{ A tibble with the resolution audit trail. } \description{ Returns the resolution tibble attached to a basket-mode result of -[cog_gov_search()]. One row per input entry; `status` is one of -`"resolved"`, `"largest_pop"`, `"ambiguous"`, `"no_match"`. By default -the `candidates` list-column is dropped for readable printing; pass -`expand_candidates = TRUE` to keep it. +\code{\link[=cog_gov_search]{cog_gov_search()}}. One row per input entry; \code{status} is one of +\code{"resolved"}, \code{"largest_pop"}, \code{"ambiguous"}, \code{"no_match"}. By default +the \code{candidates} list-column is dropped for readable printing; pass +\code{expand_candidates = TRUE} to keep it. } \examples{ \dontrun{ diff --git a/man/cog_basket_unresolved.Rd b/man/cog_basket_unresolved.Rd index e6a5145..eca7a4f 100644 --- a/man/cog_basket_unresolved.Rd +++ b/man/cog_basket_unresolved.Rd @@ -7,15 +7,15 @@ cog_basket_unresolved(x) } \arguments{ -\item{x}{A tibble returned by basket-mode [cog_gov_search()].} +\item{x}{A tibble returned by basket-mode \code{\link[=cog_gov_search]{cog_gov_search()}}.} } \value{ -A tibble (subset of [cog_basket_resolution()]). +A tibble (subset of \code{\link[=cog_basket_resolution]{cog_basket_resolution()}}). } \description{ -Convenience wrapper that returns just the rows where `status` is -`"ambiguous"` or `"no_match"` — the ones the user likely wants to -refine before piping into a query verb. The `candidates` list-column +Convenience wrapper that returns just the rows where \code{status} is +\code{"ambiguous"} or \code{"no_match"} — the ones the user likely wants to +refine before piping into a query verb. The \code{candidates} list-column is preserved so the user can drill into ambiguous match sets. } \examples{ diff --git a/man/cog_categories.Rd b/man/cog_categories.Rd index 8e72212..6142ef0 100644 --- a/man/cog_categories.Rd +++ b/man/cog_categories.Rd @@ -7,33 +7,33 @@ cog_categories(type = NULL, pattern = NULL) } \arguments{ -\item{type}{Either `NULL` (default, every row: expenditure, revenue and -balance), `"spending"`, `"revenue"`, or `"balance"`.} +\item{type}{Either \code{NULL} (default, every row: expenditure, revenue and +balance), \code{"spending"}, \code{"revenue"}, or \code{"balance"}.} \item{pattern}{Optional regex matched case-insensitively against the -`category` column (e.g. `"Police"` or `"Tax"`).} +\code{category} column (e.g. \code{"Police"} or \code{"Tax"}).} } \value{ -Tibble with columns `category`, `category_type`, `subtype`, - `n_codes`, `item_codes` (comma-separated, alphabetical). Sorted by - `category_type`, `category`, `subtype`. Includes one row per flow for the - reserved pseudo-category `"All Categories"`, which carries `NA` for - `subtype`, `n_codes` and `item_codes` because it is a query mode rather - than a crosswalk entry — see [cog_spending()]'s `category` argument. +Tibble with columns \code{category}, \code{category_type}, \code{subtype}, +\code{n_codes}, \code{item_codes} (comma-separated, alphabetical). Sorted by +\code{category_type}, \code{category}, \code{subtype}. Includes one row per flow for the +reserved pseudo-category \code{"All Categories"}, which carries \code{NA} for +\code{subtype}, \code{n_codes} and \code{item_codes} because it is a query mode rather +than a crosswalk entry — see \code{\link[=cog_spending]{cog_spending()}}'s \code{category} argument. } \description{ Returns the category taxonomy exposed by the corpus's -`summary_categories` view, grouped to one row per -`(category, subtype)` pair. Use this to discover valid `category` -values for [cog_spending()] / [cog_revenue()] / [cog_balances()] / -[cog_geographic_rollup()] and to audit which Census item codes feed +\code{summary_categories} view, grouped to one row per +\verb{(category, subtype)} pair. Use this to discover valid \code{category} +values for \code{\link[=cog_spending]{cog_spending()}} / \code{\link[=cog_revenue]{cog_revenue()}} / \code{\link[=cog_balances]{cog_balances()}} / +\code{\link[=cog_geographic_rollup]{cog_geographic_rollup()}} and to audit which Census item codes feed each category. } \details{ -`subtype` COALESCEs the crosswalk's three subtype columns, so it carries -`spend_subtype` on expenditure rows, `revenue_subtype` on revenue rows and -`balance_subtype` on balance rows. Note that [cog_balances()] itself takes -no `subtype` argument — for holdings, `category` is a strict coarsening of -`balance_subtype` — but the value is surfaced here because it is the +\code{subtype} COALESCEs the crosswalk's three subtype columns, so it carries +\code{spend_subtype} on expenditure rows, \code{revenue_subtype} on revenue rows and +\code{balance_subtype} on balance rows. Note that \code{\link[=cog_balances]{cog_balances()}} itself takes +no \code{subtype} argument — for holdings, \code{category} is a strict coarsening of +\code{balance_subtype} — but the value is surfaced here because it is the discovery surface downstream consumers build their vocabulary from. } diff --git a/man/cog_explain.Rd b/man/cog_explain.Rd index 6a4e712..46b7fce 100644 --- a/man/cog_explain.Rd +++ b/man/cog_explain.Rd @@ -7,18 +7,18 @@ cog_explain(result, format = c("print", "list")) } \arguments{ -\item{result}{A tibble returned by a `cog_*` verb.} +\item{result}{A tibble returned by a \verb{cog_*} verb.} -\item{format}{`"print"` (default) for a human-readable cli summary; -returns `result` invisibly for chaining. `"list"` returns the raw -provenance list (identical to `attr(result, "provenance")`).} +\item{format}{\code{"print"} (default) for a human-readable cli summary; +returns \code{result} invisibly for chaining. \code{"list"} returns the raw +provenance list (identical to \code{attr(result, "provenance")}).} } \value{ -Either `result` (invisibly) or the provenance list. +Either \code{result} (invisibly) or the provenance list. } \description{ Prints the structured provenance attached to a tibble returned by any -`cog_*` verb, or returns it as a list for downstream use (MCP tools, +\verb{cog_*} verb, or returns it as a list for downstream use (MCP tools, dashboards, JSON export). } \section{Two kinds of series break}{ @@ -26,28 +26,29 @@ dashboards, JSON export). Catalogued breaks reach you without being asked for, in two disjoint fields, because a caveat about one series and a caveat about the whole corpus are different claims: +\itemize{ +\item \strong{\code{series_break_refs}} — breaks matched against the item codes actually +present in this result. A break in one code you queried. +\item \strong{\code{corpus_break_refs}} — breaks catalogued with \code{fin_code = "ALL"}, +which are statements about the corpus rather than about any one code: +dollar precision across the 1976/1977 boundary (\code{SB085}), imputation +exclusion from FY2002 (\code{SB087}), the FY2012 dense-to-sparse +representation change (\code{SB194}), and the FY2017 government-identifier +change (\code{SB086}). These are selected on the break-year window alone. +} -* **`series_break_refs`** — breaks matched against the item codes actually - present in this result. A break in one code you queried. -* **`corpus_break_refs`** — breaks catalogued with `fin_code = "ALL"`, - which are statements about the corpus rather than about any one code: - dollar precision across the 1976/1977 boundary (`SB085`), imputation - exclusion from FY2002 (`SB087`), the FY2012 dense-to-sparse - representation change (`SB194`), and the FY2017 government-identifier - change (`SB086`). These are selected on the break-year window alone. - -`SB194` is the one most likely to matter: a query spanning FY2011 to FY2012 +\code{SB194} is the one most likely to matter: a query spanning FY2011 to FY2012 crosses the boundary where an absent cell stops meaning "Census published $0" and starts meaning "not reported". } \section{Other provenance blocks}{ -`transformations$units_conversion` records the `$1,000s`-to-dollars +\code{transformations$units_conversion} records the \verb{$1,000s}-to-dollars multiply that every amount column has already had applied. -`transformations$per_capita` records the population denominator and its -year range. `coverage` and `coverage_mode` appear on multi-government -results (see [cog_geographic_rollup()]). `completion` appears when -`complete = TRUE`. `balance_caveats` appears on [cog_balances()] results. +\code{transformations$per_capita} records the population denominator and its +year range. \code{coverage} and \code{coverage_mode} appear on multi-government +results (see \code{\link[=cog_geographic_rollup]{cog_geographic_rollup()}}). \code{completion} appears when +\code{complete = TRUE}. \code{balance_caveats} appears on \code{\link[=cog_balances]{cog_balances()}} results. } diff --git a/man/cog_find_peers.Rd b/man/cog_find_peers.Rd index 6de2665..88a571f 100644 --- a/man/cog_find_peers.Rd +++ b/man/cog_find_peers.Rd @@ -16,41 +16,41 @@ cog_find_peers( ) } \arguments{ -\item{target_govid}{Character scalar — `canonical_govid` of the target.} +\item{target_govid}{Character scalar — \code{canonical_govid} of the target.} -\item{year}{Integer scalar. Cohort vintage. When `NULL` (default), uses the +\item{year}{Integer scalar. Cohort vintage. When \code{NULL} (default), uses the most recent year for which the target has an observed population in -`gov_population_yearly`.} +\code{gov_population_yearly}.} -\item{same_type}{If `TRUE` (default) restrict peers to the target's -`govs_type`.} +\item{same_type}{If \code{TRUE} (default) restrict peers to the target's +\code{govs_type}.} -\item{same_state}{If `TRUE` restrict peers to the target's `fips_state`. -Default `FALSE`.} +\item{same_state}{If \code{TRUE} restrict peers to the target's \code{fips_state}. +Default \code{FALSE}.} \item{pop_range}{Length-2 numeric vector giving lower/upper bounds.} -\item{is_ratio}{If `TRUE` (default) `pop_range` is multiplied by the -target's population at `year` to produce absolute bounds. If `FALSE`, -`pop_range` is interpreted as absolute population counts.} +\item{is_ratio}{If \code{TRUE} (default) \code{pop_range} is multiplied by the +target's population at \code{year} to produce absolute bounds. If \code{FALSE}, +\code{pop_range} is interpreted as absolute population counts.} \item{max_peers}{Integer cap on the number of peers returned.} -\item{coverage}{Survey-cycle handling; see [cog_peer_compare()]. Here it -governs the cohort VINTAGE when `year` is `NULL`: `"census"` snaps to the +\item{coverage}{Survey-cycle handling; see \code{\link[=cog_peer_compare]{cog_peer_compare()}}. Here it +governs the cohort VINTAGE when \code{year} is \code{NULL}: \code{"census"} snaps to the most recent census year with an observed population, so a cohort is not built from a sample year in which most of the candidate universe is -absent. `"consistent"` needs a year range, which cohort selection does not -have, so it selects like `"all"` and is carried on the result as -`attr(x, "coverage")` for [cog_peer_compare()].} +absent. \code{"consistent"} needs a year range, which cohort selection does not +have, so it selects like \code{"all"} and is carried on the result as +\code{attr(x, "coverage")} for \code{\link[=cog_peer_compare]{cog_peer_compare()}}.} } \value{ -Tibble with columns `canonical_govid`, `gov_name`, `fips_state`, - `population`, `pop_ratio`, `rank`. The cohort year is attached as - `attr(x, "cohort_year")`. +Tibble with columns \code{canonical_govid}, \code{gov_name}, \code{fips_state}, +\code{population}, \code{pop_ratio}, \code{rank}. The cohort year is attached as +\code{attr(x, "cohort_year")}. } \description{ Selects peer governments by combinations of government type, state, and -population range at a chosen `year`. Peers are ordered by `|log(pop_ratio)|` +population range at a chosen \code{year}. Peers are ordered by \verb{|log(pop_ratio)|} ascending (closest to the target's population first). } diff --git a/man/cog_fiscal_periods.Rd b/man/cog_fiscal_periods.Rd index 5b5448f..4f88731 100644 --- a/man/cog_fiscal_periods.Rd +++ b/man/cog_fiscal_periods.Rd @@ -7,19 +7,19 @@ cog_fiscal_periods(govid, years) } \arguments{ -\item{govid}{Character vector of `canonical_govid` values, or a data frame -with a `canonical_govid` column.} +\item{govid}{Character vector of \code{canonical_govid} values, or a data frame +with a \code{canonical_govid} column.} \item{years}{Integer vector of survey years.} } \value{ Tibble with one row per requested government and year, in the - order `govid` x `years`: `canonical_govid`, `year`, `fiscal_year_end` - (integer MMDD), `period_start` and `period_end` (Dates, inclusive). +order \code{govid} x \code{years}: \code{canonical_govid}, \code{year}, \code{fiscal_year_end} +(integer MMDD), \code{period_start} and \code{period_end} (Dates, inclusive). } \description{ Returns the calendar months each survey year covers for each government. -The corpus's `year` is the Census survey year, and a survey year covers +The corpus's \code{year} is the Census survey year, and a survey year covers different months for different governments. } \section{The survey-year rule}{ @@ -27,17 +27,18 @@ different months for different governments. Census assigns each government's fiscal year to a survey year by when the fiscal year ended. Survey year Y holds the fiscal year that ended between July 1 of Y-1 and June 30 of Y. The corpus records each government-year's -fiscal year end as `fiscal_year_end`, an MMDD integer such as `630` or -`1231`. +fiscal year end as \code{fiscal_year_end}, an MMDD integer such as \code{630} or +\code{1231}. Survey year 2017 therefore covers, for a county, city or township: - - * `fiscal_year_end = 630` (June 30): the fiscal year ending June 30, - 2017, so July 2016 to June 2017. - * `930` (September 30): the fiscal year ending September 30, 2016, so - October 2015 to September 2016. - * `1231` (December 31): the fiscal year ending December 31, 2016, so - January to December 2016. +\itemize{ +\item \code{fiscal_year_end = 630} (June 30): the fiscal year ending June 30, +2017, so July 2016 to June 2017. +\item \code{930} (September 30): the fiscal year ending September 30, 2016, so +October 2015 to September 2016. +\item \code{1231} (December 31): the fiscal year ending December 31, 2016, so +January to December 2016. +} A city with a December year end and a city with a June year end are both "2017" in the corpus, but their figures are six months apart. A September @@ -55,11 +56,11 @@ way. That treatment has not been checked against the data. For New York the same months. A government can change its fiscal year end, so the periods are looked up -per government-year. Where the corpus has no `fiscal_year_end` for a +per government-year. Where the corpus has no \code{fiscal_year_end} for a government-year, or the government has no rows that year, the period is -`NA`. Most of FY1993 is `NA`: 99% of its government-years have no usable -value in the public corpus as of November 2026. So do 5% to 11% in FY1978 -and FY1987 to FY1990, and under 3% in every other year. +\code{NA}. Most of FY1993 is \code{NA}: 99\% of its government-years have no usable +value in the public corpus as of November 2026. So do 5\% to 11\% in FY1978 +and FY1987 to FY1990, and under 3\% in every other year. From FY2023 the source files mark some rows as estimates carried forward from an earlier year. The periods here describe the survey year, not the @@ -76,7 +77,7 @@ cog_fiscal_periods( } } \seealso{ -[cog_survey_year()] for the reverse mapping; the `fiscal_period` - argument of [cog_spending()], [cog_revenue()] and [cog_balances()] to get - the same columns on every row. +\code{\link[=cog_survey_year]{cog_survey_year()}} for the reverse mapping; the \code{fiscal_period} +argument of \code{\link[=cog_spending]{cog_spending()}}, \code{\link[=cog_revenue]{cog_revenue()}} and \code{\link[=cog_balances]{cog_balances()}} to get +the same columns on every row. } diff --git a/man/cog_geographic_rollup.Rd b/man/cog_geographic_rollup.Rd index aa38128..dc034a9 100644 --- a/man/cog_geographic_rollup.Rd +++ b/man/cog_geographic_rollup.Rd @@ -16,102 +16,104 @@ cog_geographic_rollup( } \arguments{ \item{govids}{Named list with any non-empty subset of elements named -`state`, `county`, `city`. Each element is a character vector of -`canonical_govid` values. At least one layer required.} +\code{state}, \code{county}, \code{city}. Each element is a character vector of +\code{canonical_govid} values. At least one layer required.} \item{category}{Single category name or character vector (passed through -to [cog_spending()]), or the reserved `"All Categories"` for one summed -row per `(year, canonical_govid, subtype)` covering every category in the -concept's scope. `"All Categories"` is the efficient way to build a +to \code{\link[=cog_spending]{cog_spending()}}), or the reserved \code{"All Categories"} for one summed +row per \verb{(year, canonical_govid, subtype)} covering every category in the +concept's scope. \code{"All Categories"} is the efficient way to build a geographic total: without it a caller must issue one rollup per category and sum the results themselves.} \item{years}{Integer vector of years.} -\item{per_capita}{If `TRUE`, per-capita uses each gov's own per-year -population from `gov_population_yearly`. Govs with missing population +\item{per_capita}{If \code{TRUE}, per-capita uses each gov's own per-year +population from \code{gov_population_yearly}. Govs with missing population are excluded from the result.} -\item{adjust_to_year}{Integer base year for CPI-U conversion, or `NULL`.} +\item{adjust_to_year}{Integer base year for CPI-U conversion, or \code{NULL}.} -\item{expenditure_concept}{`"primary"` (default), `"direct"`, or -`"total"` -- see [cog_spending()] for the three concepts. `"total"` is +\item{expenditure_concept}{\code{"primary"} (default), \code{"direct"}, or +\code{"total"} -- see \code{\link[=cog_spending]{cog_spending()}} for the three concepts. \code{"total"} is refused here because combining Total across multiple layers of government double-counts intergovernmental transfers (a state's payment to a school district is the same dollar the district reports as its own -Direct spending); `"primary"` and `"direct"` combine safely.} +Direct spending); \code{"primary"} and \code{"direct"} combine safely.} \item{coverage}{How to handle the Census of Governments survey cycle, - which is a **complete census only in years ending in 2 and 7** -- every - other year is a sample, and the sample varies enormously (on the bundled - fixture, Wisconsin's 608-city universe reports 597 governments in FY2012 - and 112 in FY2019). - - * `"all"` (default) -- every unit that reported that year. Unchanged - behaviour, so existing code keeps working. - * `"census"` -- census years only. Aborts if the requested range holds - none, rather than silently returning nothing. - * `"consistent"` -- only units reporting in *every* requested year, giving - a balanced panel. +which is a \strong{complete census only in years ending in 2 and 7} -- every +other year is a sample, and the sample varies enormously (on the bundled +fixture, Wisconsin's 608-city universe reports 597 governments in FY2012 +and 112 in FY2019). +\itemize{ +\item \code{"all"} (default) -- every unit that reported that year. Unchanged +behaviour, so existing code keeps working. +\item \code{"census"} -- census years only. Aborts if the requested range holds +none, rather than silently returning nothing. +\item \code{"consistent"} -- only units reporting in \emph{every} requested year, giving +a balanced panel. +} - Regardless of mode, `provenance$coverage` always carries per-year - `n_units_expected`, `n_units_collected`, `n_units_reporting` and - `is_census_year`, and `provenance$coverage_mode` records the mode. - `is_census_year` is a statement about the **survey calendar**, never a - claim of completeness: FY1967 is a census year in which only 97 of - Wisconsin's 608 cities report. `n_units_reporting` is - category-conditional and is not a response rate on its own -- see - "Reading `coverage`" below for what each counter answers.} +Regardless of mode, \code{provenance$coverage} always carries per-year +\code{n_units_expected}, \code{n_units_collected}, \code{n_units_reporting} and +\code{is_census_year}, and \code{provenance$coverage_mode} records the mode. +\code{is_census_year} is a statement about the \strong{survey calendar}, never a +claim of completeness: FY1967 is a census year in which only 97 of +Wisconsin's 608 cities report. \code{n_units_reporting} is +category-conditional and is not a response rate on its own -- see +"Reading \code{coverage}" below for what each counter answers.} } \value{ -Tibble with columns `year`, `layer`, `canonical_govid`, `gov_name`, - `spend_subtype`, `category`, `amt_nominal`, optional `amt_real` / - `amt_per_capita_nominal` / `amt_per_capita_real`, optional `pop_source`, - `codes_included`, `aggregate_fallback`, `scope_note`, `notes`. Carries a - `provenance` attribute with `verb = "cog_geographic_rollup"`, `layers`, - and `rollup$included_govids` / `rollup$excluded_govids`. +Tibble with columns \code{year}, \code{layer}, \code{canonical_govid}, \code{gov_name}, +\code{spend_subtype}, \code{category}, \code{amt_nominal}, optional \code{amt_real} / +\code{amt_per_capita_nominal} / \code{amt_per_capita_real}, optional \code{pop_source}, +\code{codes_included}, \code{aggregate_fallback}, \code{scope_note}, \code{notes}. Carries a +\code{provenance} attribute with \code{verb = "cog_geographic_rollup"}, \code{layers}, +and \code{rollup$included_govids} / \code{rollup$excluded_govids}. } \description{ -Wraps [cog_spending()], tags each row with its layer, and attaches a -human-readable `scope_note` documenting geographic-scope caveats (e.g. +Wraps \code{\link[=cog_spending]{cog_spending()}}, tags each row with its layer, and attaches a +human-readable \code{scope_note} documenting geographic-scope caveats (e.g. "county totals include areas outside the listed city"). Useful for "place portraits" that compare a city to the surrounding county and containing state on one set of axes. } \details{ -When `per_capita = TRUE`, rows whose government has no observed -population in that year (`pop_source == "unavailable"`) are dropped from +When \code{per_capita = TRUE}, rows whose government has no observed +population in that year (\code{pop_source == "unavailable"}) are dropped from the result. The dropped govids are recorded in -`provenance$rollup$excluded_govids`. This excludes special districts +\code{provenance$rollup$excluded_govids}. This excludes special districts (gov type 4) and school districts (gov type 5) from per-capita rollups -by design — see `vignette('population-denominators')`. +by design — see \code{vignette('population-denominators')}. } -\section{Reading `coverage`}{ +\section{Reading \code{coverage}}{ -`provenance$coverage` carries three per-year counters: - - * `n_units_expected` -- how many governments you asked about. - * `n_units_collected` -- how many of those appear in the corpus at all - that year (in ANY category), separating governments Census did not - collect from governments it did. - * `n_units_reporting` -- how many have rows for the SPECIFIC category you - requested. This is always <= n_units_collected. A collected government - can have no "Police" rows and still pay for policing: the rows leave out - intergovernmental expenditure, so a city that pays the county sheriff - and reports the payment as intergovernmental (code `M62`) has none. Of - 34 cities with documented sheriff contracts, nine of 102 city-years - (FY2012, FY2017 and FY2022; corpus build of 2026-10-26) looked like - this, and the other 93 reported direct Police spending. +\code{provenance$coverage} carries three per-year counters: +\itemize{ +\item \code{n_units_expected} -- how many governments you asked about. +\item \code{n_units_collected} -- how many of those appear in the corpus at all +that year (in ANY category), separating governments Census did not +collect from governments it did. +\item \code{n_units_reporting} -- how many have rows for the SPECIFIC category you +requested. This is always <= n_units_collected. A collected government +can have no "Police" rows and still pay for policing: the rows leave out +intergovernmental expenditure, so a city that pays the county sheriff +and reports the payment as intergovernmental (code \code{M62}) has none. Of +34 cities with documented sheriff contracts, nine of 102 city-years +(FY2012, FY2017 and FY2022; corpus build of 2026-10-26) looked like +this, and the other 93 reported direct Police spending. +} -**`n_units_reporting` is category-conditional** and therefore **not a -response rate**: `n_units_reporting / n_units_expected` conflates sampling +\strong{\code{n_units_reporting} is category-conditional} and therefore \strong{not a +response rate}: \code{n_units_reporting / n_units_expected} conflates sampling (never collected) with collected governments that have no rows in your -category. Use `n_units_collected / n_units_expected` for the true -collection rate, and `n_units_reporting / n_units_collected` for category +category. Use \code{n_units_collected / n_units_expected} for the true +collection rate, and \code{n_units_reporting / n_units_collected} for category participation among collected units. In FY2022, a census year, 393 of Georgia's 567 cities report -`category = "Police"`. Of the other 174, 32 were not collected and 142 were +\code{category = "Police"}. Of the other 174, 32 were not collected and 142 were collected with no Police rows. A city that contracts with the county sheriff lands in the second group only when it reports no direct Police spending, for example when it files the payment as intergovernmental expenditure; the @@ -120,7 +122,7 @@ counters do not say how many of the 142 do. A census year and a sample year collect different sets of governments, so participation across the two mixes a change in which governments were collected with any change in spending. Compare census years with each other, -or the same governments across years. `is_census_year` marks which is which, -and `vignette("coverage-counters")` has worked examples. +or the same governments across years. \code{is_census_year} marks which is which, +and \code{vignette("coverage-counters")} has worked examples. } diff --git a/man/cog_gov_search.Rd b/man/cog_gov_search.Rd index 1656b15..22f33a6 100644 --- a/man/cog_gov_search.Rd +++ b/man/cog_gov_search.Rd @@ -16,69 +16,72 @@ cog_gov_search( \item{name}{Character vector of place name(s). Length 1 = utility mode; length >1 = basket mode.} -\item{state}{2-letter USPS abbreviation (e.g. `"FL"`), FIPS integer -(e.g. `12`), or `NULL`. In basket mode, length 1 recycles across -all entries; otherwise must match `length(name)`.} +\item{state}{2-letter USPS abbreviation (e.g. \code{"FL"}), FIPS integer +(e.g. \code{12}), or \code{NULL}. In basket mode, length 1 recycles across +all entries; otherwise must match \code{length(name)}.} -\item{type}{Government type: integer in `0:3` or one of `"state"`, -`"county"`, `"city"`, `"township"`, or `NA`/`NULL`. Per-row optional -in basket mode (recycles from length 1). Excluded types `4`/`5` (or -`"special_district"` / `"school_district"`) trigger an explanatory +\item{type}{Government type: integer in \code{0:3} or one of \code{"state"}, +\code{"county"}, \code{"city"}, \code{"township"}, or \code{NA}/\code{NULL}. Per-row optional +in basket mode (recycles from length 1). Excluded types \code{4}/\code{5} (or +\code{"special_district"} / \code{"school_district"}) trigger an explanatory message and an empty result.} -\item{limit}{Maximum number of rows to return, applied in SQL. `NULL` +\item{limit}{Maximum number of rows to return, applied in SQL. \code{NULL} (default) returns every match -- which, with no other filter, is the entire crosswalk. Utility mode only: pagination has no meaning in basket mode, where the result is one resolved row per requested name in input order, and is refused there with class -`uscogdata_basket_pagination_conflict`.} +\code{uscogdata_basket_pagination_conflict}.} -\item{offset}{Rows to skip before `limit` starts counting (0-based). -Ignored if `limit` is `NULL`; defaults to `0L` when `limit` is set.} +\item{offset}{Rows to skip before \code{limit} starts counting (0-based). +Ignored if \code{limit} is \code{NULL}; defaults to \code{0L} when \code{limit} is set.} } \value{ -A tibble of `canonical_fips_xwalk` rows. In utility mode, all - matches sorted by `population_acs` desc, ties broken by - `canonical_govid`. In basket mode, resolved rows in input order, with - `attr(., "resolution")` set to the sidecar tibble. +A tibble of \code{canonical_fips_xwalk} rows. In utility mode, all +matches sorted by \code{population_acs} desc, ties broken by +\code{canonical_govid}. In basket mode, resolved rows in input order, with +\code{attr(., "resolution")} set to the sidecar tibble. - When `limit` is set, carries a `total_rows` attribute: the full - unpaginated match count, computed by the same query (`COUNT(*) OVER()`) - rather than a second scan. +When \code{limit} is set, carries a \code{total_rows} attribute: the full +unpaginated match count, computed by the same query (\verb{COUNT(*) OVER()}) +rather than a second scan. } \description{ -Resolves human-readable place names into rows of `canonical_fips_xwalk`, +Resolves human-readable place names into rows of \code{canonical_fips_xwalk}, the cross-vintage canonical-government registry. Operates in two modes: } \details{ -* **Utility mode** (single `name`, the original behavior): returns all - rows whose `gov_name` contains `name` as a **literal, case-insensitive - substring**, sorted by `population_acs` descending. Useful for - exploratory lookups. Regex metacharacters in `name` are escaped, so a - government is findable by its own complete name even when that name - contains parentheses or a period. -* **Basket mode** (`length(name) > 1`): resolves each input row to a - single canonical govid and returns a tibble in input order, suitable - for piping straight into [cog_spending()] / [cog_revenue()] / - [cog_geographic_rollup()]. Carries an audit sidecar accessible via - [cog_basket_resolution()] / [cog_basket_unresolved()]. - +\itemize{ +\item \strong{Utility mode} (single \code{name}, the original behavior): returns all +rows whose \code{gov_name} contains \code{name} as a \strong{literal, case-insensitive +substring}, sorted by \code{population_acs} descending. Useful for +exploratory lookups. Regex metacharacters in \code{name} are escaped, so a +government is findable by its own complete name even when that name +contains parentheses or a period. +\item \strong{Basket mode} (\code{length(name) > 1}): resolves each input row to a +single canonical govid and returns a tibble in input order, suitable +for piping straight into \code{\link[=cog_spending]{cog_spending()}} / \code{\link[=cog_revenue]{cog_revenue()}} / +\code{\link[=cog_geographic_rollup]{cog_geographic_rollup()}}. Carries an audit sidecar accessible via +\code{\link[=cog_basket_resolution]{cog_basket_resolution()}} / \code{\link[=cog_basket_unresolved]{cog_basket_unresolved()}}. +} -**Basket-mode resolution algorithm** (per input row): -1. Filter `canonical_fips_xwalk` by `state` and (if non-NA) `type`. -2. **Exact pass:** case-insensitive equality against `gov_name`. - Single hit -> resolved. Multiple -> step 4. -3. **Substring fallback:** case-insensitive literal substring against - `gov_name` (metacharacters escaped). - Single hit -> resolved (`match_method = "substring"`). Zero hits -> - `status = "no_match"`. Multiple hits -> step 4. -4. **Disambiguation:** if matches share one `govs_type`, pick the - largest-population row (`status = "largest_pop"`). If they span >=2 - types, no row is added (`status = "ambiguous"`); the user should - re-run with `type` specified. +\strong{Basket-mode resolution algorithm} (per input row): +\enumerate{ +\item Filter \code{canonical_fips_xwalk} by \code{state} and (if non-NA) \code{type}. +\item \strong{Exact pass:} case-insensitive equality against \code{gov_name}. +Single hit -> resolved. Multiple -> step 4. +\item \strong{Substring fallback:} case-insensitive literal substring against +\code{gov_name} (metacharacters escaped). +Single hit -> resolved (\code{match_method = "substring"}). Zero hits -> +\code{status = "no_match"}. Multiple hits -> step 4. +\item \strong{Disambiguation:} if matches share one \code{govs_type}, pick the +largest-population row (\code{status = "largest_pop"}). If they span >=2 +types, no row is added (\code{status = "ambiguous"}); the user should +re-run with \code{type} specified. +} Resolved rows form the returned tibble in input order. Unresolved -inputs (`ambiguous` / `no_match`) appear only in the sidecar. +inputs (\code{ambiguous} / \code{no_match}) appear only in the sidecar. } \examples{ \dontrun{ @@ -113,6 +116,6 @@ refined <- cog_gov_search( } } \seealso{ -[cog_basket_resolution()], [cog_basket_unresolved()], - [cog_spending()], [cog_revenue()]. +\code{\link[=cog_basket_resolution]{cog_basket_resolution()}}, \code{\link[=cog_basket_unresolved]{cog_basket_unresolved()}}, +\code{\link[=cog_spending]{cog_spending()}}, \code{\link[=cog_revenue]{cog_revenue()}}. } diff --git a/man/cog_manifest.Rd b/man/cog_manifest.Rd index a04718f..85ad749 100644 --- a/man/cog_manifest.Rd +++ b/man/cog_manifest.Rd @@ -7,12 +7,12 @@ cog_manifest() } \value{ -Named list: `schema_version`, `built_at`, `pipeline_commit`, - `data_vintage`, `scope`, `years` (schema v5+), `schema`, `files`. +Named list: \code{schema_version}, \code{built_at}, \code{pipeline_commit}, +\code{data_vintage}, \code{scope}, \code{years} (schema v5+), \code{schema}, \code{files}. } \description{ Opens a session (connecting to the configured corpus) if none is active, -then returns the manifest exactly as parsed from `manifest.json`. Useful -for consumers that need the published year range (`years` block, schema +then returns the manifest exactly as parsed from \code{manifest.json}. Useful +for consumers that need the published year range (\code{years} block, schema v5+) or the partition list without issuing a data query. } diff --git a/man/cog_mirror.Rd b/man/cog_mirror.Rd index 23b292e..8099953 100644 --- a/man/cog_mirror.Rd +++ b/man/cog_mirror.Rd @@ -14,22 +14,22 @@ cog_mirror( \arguments{ \item{dest}{Destination directory. Created if missing.} -\item{include}{Subset of `c("long", "metadata", "docs")` controlling +\item{include}{Subset of \code{c("long", "metadata", "docs")} controlling which manifest sections to mirror.} -\item{overwrite}{If `TRUE`, re-copy even when the local SHA matches.} +\item{overwrite}{If \code{TRUE}, re-copy even when the local SHA matches.} -\item{progress}{If `TRUE`, show a cli progress bar.} +\item{progress}{If \code{TRUE}, show a cli progress bar.} } \value{ -Invisibly, a tibble of `(path, sha256, size_bytes, status)` - rows where `status` is `"downloaded"` or `"cached"`. +Invisibly, a tibble of \verb{(path, sha256, size_bytes, status)} +rows where \code{status} is \code{"downloaded"} or \code{"cached"}. } \description{ Downloads (or copies, for local-path fixture URLs) every file listed in -the session's `manifest.json` into `dest`, preserving the relative path +the session's \code{manifest.json} into \code{dest}, preserving the relative path structure. Files already present with a matching SHA-256 hash are -skipped unless `overwrite = TRUE`. The resulting directory can be -pointed at via `options(uscogdata.url = paste0(dest, "/"))` for offline +skipped unless \code{overwrite = TRUE}. The resulting directory can be +pointed at via \code{options(uscogdata.url = paste0(dest, "/"))} for offline analysis. } diff --git a/man/cog_peer_compare.Rd b/man/cog_peer_compare.Rd index 1c5d4c8..6afba08 100644 --- a/man/cog_peer_compare.Rd +++ b/man/cog_peer_compare.Rd @@ -18,123 +18,123 @@ cog_peer_compare( \arguments{ \item{target_govid}{Character scalar.} -\item{peers}{A tibble from [cog_find_peers()] or a character vector of -`canonical_govid`s.} +\item{peers}{A tibble from \code{\link[=cog_find_peers]{cog_find_peers()}} or a character vector of +\code{canonical_govid}s.} \item{category}{Character scalar or vector.} \item{years}{Integer vector.} -\item{per_capita}{Default `TRUE` — peer compare usually normalizes by +\item{per_capita}{Default \code{TRUE} — peer compare usually normalizes by population.} -\item{adjust_to_year}{Integer base year for CPI-U conversion or `NULL`.} +\item{adjust_to_year}{Integer base year for CPI-U conversion or \code{NULL}.} -\item{expenditure_concept}{`"primary"` (default), `"direct"`, or -`"total"` -- see [cog_spending()] for the three concepts. `"total"` is +\item{expenditure_concept}{\code{"primary"} (default), \code{"direct"}, or +\code{"total"} -- see \code{\link[=cog_spending]{cog_spending()}} for the three concepts. \code{"total"} is refused here because combining Total across peer sets counts -intergovernmental transfers twice; `"primary"` and `"direct"` combine +intergovernmental transfers twice; \code{"primary"} and \code{"direct"} combine safely.} \item{coverage}{How to handle the Census of Governments survey cycle, - which is a **complete census only in years ending in 2 and 7** -- every - other year is a sample, and the sample varies enormously (on the bundled - fixture, Wisconsin's 608-city universe reports 597 governments in FY2012 - and 112 in FY2019). - - * `"all"` (default) -- every unit that reported that year. Unchanged - behaviour, so existing code keeps working. - * `"census"` -- census years only. Aborts if the requested range holds - none, rather than silently returning nothing. - * `"consistent"` -- only units reporting in *every* requested year, giving - a balanced panel. - - Regardless of mode, `provenance$coverage` always carries per-year - `n_units_expected`, `n_units_collected`, `n_units_reporting` and - `is_census_year`, and `provenance$coverage_mode` records the mode. - `is_census_year` is a statement about the **survey calendar**, never a - claim of completeness: FY1967 is a census year in which only 97 of - Wisconsin's 608 cities report. `n_units_reporting` is - category-conditional and is not a response rate on its own -- see - "Reading `coverage`" below for what each counter answers. - - The comparison target is exempt from `"consistent"` balancing -- it is the - subject of the comparison, not a member of the cohort -- and the - `summary_*` quantiles are computed AFTER the filter, so they describe the - cohort actually returned. `n_units_reporting` counts peers only, against - the cohort size: "3 of your 15 peers reported in FY2019".} +which is a \strong{complete census only in years ending in 2 and 7} -- every +other year is a sample, and the sample varies enormously (on the bundled +fixture, Wisconsin's 608-city universe reports 597 governments in FY2012 +and 112 in FY2019). +\itemize{ +\item \code{"all"} (default) -- every unit that reported that year. Unchanged +behaviour, so existing code keeps working. +\item \code{"census"} -- census years only. Aborts if the requested range holds +none, rather than silently returning nothing. +\item \code{"consistent"} -- only units reporting in \emph{every} requested year, giving +a balanced panel. +} + +Regardless of mode, \code{provenance$coverage} always carries per-year +\code{n_units_expected}, \code{n_units_collected}, \code{n_units_reporting} and +\code{is_census_year}, and \code{provenance$coverage_mode} records the mode. +\code{is_census_year} is a statement about the \strong{survey calendar}, never a +claim of completeness: FY1967 is a census year in which only 97 of +Wisconsin's 608 cities report. \code{n_units_reporting} is +category-conditional and is not a response rate on its own -- see +"Reading \code{coverage}" below for what each counter answers. + +The comparison target is exempt from \code{"consistent"} balancing -- it is the +subject of the comparison, not a member of the cohort -- and the +\verb{summary_*} quantiles are computed AFTER the filter, so they describe the +cohort actually returned. \code{n_units_reporting} counts peers only, against +the cohort size: "3 of your 15 peers reported in FY2019".} } \value{ -Tibble matching [cog_spending()]'s columns, plus a `role` - column taking values `"target"`, `"peer"`, `"summary_p25"`, - `"summary_p50"`, or `"summary_p75"`, `target_rank` (target's rank - among target+peers at `max(years)`, NA for other rows), and - `cohort_year` (the year used to build the peer cohort, read from - `attr(peers, "cohort_year")`; `NA` when `peers` was a bare character - vector). Provenance reports `verb = "cog_peer_compare"`, `peer_count`, - `cohort_year`, and `cohort_govids`. - - **The `summary_*` rows are per-category quantiles: they are not additive.** - Each one is computed **within each `(year, spend_subtype, - category)` cell** across the peer set, so a `summary_p50` row is *the - median peer's value in that one category*, not *the value of the median - peer's total*. The median peer for Police and the median peer for Fire - are usually different governments, so summing `summary_*` rows across - categories does not give any peer's total and misstates the band it - appears to describe — measured at −32.7% to +251.0% across 24 years on - one cohort, with a sign flip at FY2012. - - Facet by `role` **and** `category` (the documented use, and what the - rows are built for). For a genuine "median peer's total spending" line, - sum each peer's own categories first and take the quantile of those - per-government totals: - - ```r - library(dplyr) - cmp |> - filter(role %in% c("target", "peer")) |> - group_by(year, role, canonical_govid) |> - summarise(total = sum(amt_per_capita_real, na.rm = TRUE), .groups = "drop") |> - filter(role == "peer") |> - group_by(year) |> - summarise(p50 = quantile(total, 0.5, na.rm = TRUE)) - ``` +Tibble matching \code{\link[=cog_spending]{cog_spending()}}'s columns, plus a \code{role} +column taking values \code{"target"}, \code{"peer"}, \code{"summary_p25"}, +\code{"summary_p50"}, or \code{"summary_p75"}, \code{target_rank} (target's rank +among target+peers at \code{max(years)}, NA for other rows), and +\code{cohort_year} (the year used to build the peer cohort, read from +\code{attr(peers, "cohort_year")}; \code{NA} when \code{peers} was a bare character +vector). Provenance reports \code{verb = "cog_peer_compare"}, \code{peer_count}, +\code{cohort_year}, and \code{cohort_govids}. + +\strong{The \verb{summary_*} rows are per-category quantiles: they are not additive.} +Each one is computed \strong{within each \verb{(year, spend_subtype, category)} cell} across the peer set, so a \code{summary_p50} row is \emph{the +median peer's value in that one category}, not \emph{the value of the median +peer's total}. The median peer for Police and the median peer for Fire +are usually different governments, so summing \verb{summary_*} rows across +categories does not give any peer's total and misstates the band it +appears to describe — measured at −32.7\% to +251.0\% across 24 years on +one cohort, with a sign flip at FY2012. + +Facet by \code{role} \strong{and} \code{category} (the documented use, and what the +rows are built for). For a genuine "median peer's total spending" line, +sum each peer's own categories first and take the quantile of those +per-government totals: + +\if{html}{\out{