feat: bundle CPIAUCSL + .inflate() helper
Adds R/sysdata.rda with the annual-average CPIAUCSL index (1947-2026, 80 years, sourced from FRED) and an internal .inflate() helper that converts nominal amounts between two years via the ratio of CPI values. Bundling CPI in the package (rather than publishing a cpi_annual.parquet in the corpus) matches the reader-specification intent: real-dollar conversion is a verb-level option, not a corpus-level artifact, so the target_year stays flexible at query time. data-raw/cpi_annual.R carries the one-shot FRED refresh used to build sysdata.rda. Re-run when the CPI series needs to roll forward. Verified: CPI(2000)/CPI(2021) ≈ 0.635, matching the ~0.63 sanity anchor in cog_explorer's existing inflation logic. Tests: tests/testthat/test-adjust.R covers the known 2000→2021 ≈ 1.574x anchor, vectorized from_year, error cases for out-of-range years, and NA-amount preservation. 14 pass / 0 fail.
This commit is contained in:
+45
@@ -0,0 +1,45 @@
|
||||
# R/adjust.R
|
||||
# Inflation adjustment helpers using bundled CPIAUCSL annual averages.
|
||||
# The `cpi_annual` tibble (year, cpi) is stored as internal data in
|
||||
# R/sysdata.rda and built via data-raw/ on package update.
|
||||
|
||||
#' Return the bundled annual CPI table.
|
||||
#'
|
||||
#' @return Tibble with columns `year` (integer) and `cpi` (numeric, CPIAUCSL
|
||||
#' annual average, 1982-84 = 100).
|
||||
#' @noRd
|
||||
.cpi_table <- function() {
|
||||
cpi_annual
|
||||
}
|
||||
|
||||
#' Inflate (or deflate) an amount vector between two years.
|
||||
#'
|
||||
#' Converts nominal amounts in `from_year` dollars to real amounts in
|
||||
#' `to_year` dollars using the bundled CPIAUCSL annual average index.
|
||||
#' Multiplies by `cpi[to_year] / cpi[from_year]`.
|
||||
#'
|
||||
#' @param amt Numeric vector of nominal amounts.
|
||||
#' @param from_year Integer or integer-like vector of source years (one per
|
||||
#' element of `amt`, or length 1).
|
||||
#' @param to_year Integer target year (scalar).
|
||||
#' @return Numeric vector of real amounts, same length as `amt`.
|
||||
#' @noRd
|
||||
.inflate <- function(amt, from_year, to_year) {
|
||||
cpi <- .cpi_table()
|
||||
from_year <- as.integer(from_year)
|
||||
to_year <- as.integer(to_year)
|
||||
if (length(to_year) != 1L) {
|
||||
cli::cli_abort("`to_year` must be a scalar.")
|
||||
}
|
||||
if (!(to_year %in% cpi$year)) {
|
||||
cli::cli_abort("CPI unavailable for to_year = {to_year}. Supported: {min(cpi$year)}-{max(cpi$year)}.")
|
||||
}
|
||||
missing_years <- setdiff(from_year[!is.na(from_year)], cpi$year)
|
||||
if (length(missing_years) > 0) {
|
||||
cli::cli_abort("CPI unavailable for from_year value(s): {missing_years}.")
|
||||
}
|
||||
lookup <- stats::setNames(cpi$cpi, as.character(cpi$year))
|
||||
cpi_from <- unname(lookup[as.character(from_year)])
|
||||
cpi_to <- unname(lookup[as.character(to_year)])
|
||||
amt * cpi_to / cpi_from
|
||||
}
|
||||
Reference in New Issue
Block a user