---
title: "CPI Adjustments"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{CPI Adjustments}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
# chunks that download hosted data are skipped on CRAN machines; set
# NOT_CRAN=true (as the pkgdown workflow does) to evaluate everything
NOT_CRAN <- identical(Sys.getenv("NOT_CRAN"), "true")
knitr::opts_chunk$set(
  message = FALSE,
  warning = FALSE,
  fig.width = 8,
  eval = NOT_CRAN
)
```

## Introduction

When analyzing education finance data across multiple years, adjusting for inflation can help produce more meaningful comparisons. `edfinr` provides built-in functionality to adjust dollar-denominated flows (revenues, expenditures, and income measures) for inflation using the Consumer Price Index for All Urban Consumers (CPI-U). See "What gets adjusted" below for the exact scope.

```{r setup, include = FALSE, eval = TRUE}
library(edfinr)
library(dplyr)
library(tidyr)
library(stringr)
library(ggplot2)
```

```{r, eval = FALSE}
library(edfinr)
library(dplyr)
library(tidyr)
library(stringr)
library(ggplot2)
```

## Understanding nominal vs. real dollars

By default, all financial data returned by `get_finance_data()` is in **nominal dollars** - the actual dollar amounts reported in each year without any inflation adjustment. This means that $1,000 in 2012 and $1,000 in 2023 are treated as equal amounts, even though they have different purchasing power.

To make valid comparisons across years, you need to convert to **real dollars** (also called constant dollars) by adjusting for inflation.

## How CPI adjustment works

`edfinr` uses the CPI-U index to adjust for inflation. The adjustment is aligned to the school year calendar:

- Each school year's CPI is calculated by averaging:
  - The second half of the first calendar year (July-December).
  - The first half of the second calendar year (January-June).

For example, the 2022-23 school year CPI combines:

- July-December 2022 (HALF2 2022).
- January-June 2023 (HALF1 2023).

## Using the cpi_adj parameter

The `get_finance_data()` function includes a `cpi_adj` parameter to automatically adjust dollar-denominated flows:

```{r example-nominal}
# Get nominal (unadjusted) data - this is the default
nominal_data <- get_finance_data(yr = "2016:2023", geo = "KY")

# View the nominal revenue for a specific district
nominal_data |>
  filter(dist_name == "Jefferson County") |>
  select(year, dist_name, rev_total, rev_total_pp)
```

```{r example-adjusted}
# Get data adjusted to 2023 dollars
real_2023_data <- get_finance_data(yr = "2016:2023", geo = "KY", cpi_adj = 2023)

# View the same district with inflation-adjusted values
real_2023_data |>
  filter(dist_name == "Jefferson County") |>
  select(year, dist_name, rev_total, rev_total_pp)
```

When `cpi_adj` is set, the returned data also includes a `cpi_adj_index` column showing the multiplier applied to each row:

```{r adj-index}
real_2023_data |>
  distinct(year, cpi_adj_index) |>
  arrange(year)
```

## What gets adjusted

When you use `cpi_adj`, dollar-denominated **flows** are automatically adjusted for inflation:

- All revenue variables (total, local, state, federal; adjusted and unadjusted, totals and per-pupil).
- Current and capital expenditure flows, including `exp_cap_total`, its detailed components, and `exp_debt_interest`.
- Median and mean household income and median property value.

Variables that are NOT adjusted include:

- Enrollment counts, demographic percentages, and any ratio or rate variables.
- **Debt and fund-balance stocks** (`debt_*`, `fund_bal_*`). These are balance-sheet levels measured at a point in time, not annual flows. `edfinr` leaves them in nominal dollars by design: debt is owed and repaid in nominal terms, and deflating stocks alongside flows invites accidental mixing of the two. Restating them in base-year dollars is a legitimate analysis choice; if yours calls for it, apply the deflator yourself.
- The **CWIFT** teacher-wage index (`cwift_est`). It is a relative labor-cost index, not a dollar amount, and is never CPI-adjusted (see the "CWIFT" article on the package website).

The flows-vs-stocks rule is easy to verify: the capital outlay flow scales, while the debt stock is identical with and without adjustment.

```{r flows-vs-stocks}
raw <- get_finance_data(yr = "2019", geo = "KY", dataset_type = "full")
adj <- get_finance_data(yr = "2019", geo = "KY", dataset_type = "full", cpi_adj = "2023")

# capital outlay (a flow) is scaled up to 2023 dollars
head(adj$exp_cap_total / raw$exp_cap_total, 3)

# long-term debt outstanding (a stock) is identical in both
identical(adj$debt_lt_end, raw$debt_lt_end)
```

## Working with the CPI index

Every dataset includes a `cpi_sy12` column that shows the CPI index relative to the 2011-12 school year:

```{r cpi-index}
# Examine the CPI index values
cpi_values <- get_finance_data(yr = "all", geo = "KY") |>
  select(year, cpi_sy12) |>
  distinct() |>
  arrange(year)

print(cpi_values)

# Calculate cumulative inflation since 2012
cpi_values |>
  mutate(
    inflation_since_2012 = (cpi_sy12 - 1) * 100,
    inflation_label = paste0(round(inflation_since_2012, 1), "%")
  )
```

## Practical example: tracking real spending over time

Here's how to analyze whether education revenue has kept pace with inflation:

```{r real-spending-analysis, fig.alt = "Two-panel line chart comparing nominal and real 2023-dollar per-pupil revenue in Kentucky by source (local, state, federal) from 2012 to 2023; the nominal series rise steadily while the real series are much flatter."}
# get multiyear data in nominal dollars
ky_nominal <- get_finance_data(yr = "all", geo = "KY", cpi_adj = "none") |>
  mutate(type = "Nominal dollars")

# get multi-year data adjusted to 2023 dollars
ky_real <- get_finance_data(yr = "all", geo = "KY", cpi_adj = "2023") |>
  mutate(type = "Real 2023 dollars")

# join data
ky_data <- bind_rows(ky_nominal, ky_real)

# calculate statewide per-pupil revenue trends for real dollars
rev_trends <- ky_data |>
  group_by(type, year) |>
  summarize(
    rev_local = sum(rev_local, na.rm = TRUE),
    rev_state = sum(rev_state, na.rm = TRUE),
    rev_fed = sum(rev_fed, na.rm = TRUE),
    enroll = sum(enroll, na.rm = TRUE)
  ) |>
  mutate(
    rev_local_pp = rev_local / enroll,
    rev_state_pp = rev_state / enroll,
    rev_fed_pp = rev_fed / enroll
  ) |>
  select(type, year, rev_local_pp:rev_fed_pp) |>
  pivot_longer(
    cols = rev_local_pp:rev_fed_pp,
    names_to = "var", values_to = "val") |>
  mutate(
    var = str_remove_all(var, "rev_"),
    var = str_remove_all(var, "_pp"),
    var = str_to_title(var),
    var = str_replace_all(var, "Fed", "Federal")
  )

# plot trends
ggplot(rev_trends) +
  geom_line(
    aes(x = year, y = val, color = var)
    ) +
  facet_wrap(~type) +
  scale_x_continuous(breaks = seq(2013, 2023, 2)) +
  scale_y_continuous(labels = scales::label_dollar()) +
  labs(
    title = "Comparing Nominal and Real Per-Pupil Revenue in Kentucky",
    subtitle = "Statewide average per-pupil revenue by source, 2012-2023",
    x = "Year",
    y = "Per-Pupil Revenue",
    color = "Revenue Source"
  ) +
  theme_minimal()
```

## Choosing a base year

You can adjust to any year from 2012 to 2023. Common choices include:

- **Most recent year** (e.g., 2023): Shows all values in current dollar terms.
- **First year of analysis**: Makes it easy to see percentage changes from baseline.
- **Midpoint year**: Minimizes the size of adjustments across the time series.

```{r base-year-comparison, fig.alt = "Line chart of Jefferson County, Kentucky per-pupil total revenue from 2012 to 2023 shown in nominal dollars, 2012 dollars, and 2023 dollars; the three lines share the same shape at different levels."}
# select ky district to assess
district_sample <- "Jefferson County"

# get data with nominal dollars and cpi-adjusted for different base years
nominal <- get_finance_data(yr = "2012:2023", geo = "KY") |>
  filter(dist_name == district_sample) |>
  select(year, rev_total_pp) |>
  mutate(type = "Nominal")

adjusted_2012 <- get_finance_data(yr = "2012:2023", geo = "KY", cpi_adj = 2012) |>
  filter(dist_name == district_sample) |>
  select(year, rev_total_pp) |>
  mutate(type = "2012 Dollars")

adjusted_2023 <- get_finance_data(yr = "2012:2023", geo = "KY", cpi_adj = 2023) |>
  filter(dist_name == district_sample) |>
  select(year, rev_total_pp) |>
  mutate(type = "2023 Dollars")

# join and plot data
bind_rows(nominal, adjusted_2012, adjusted_2023) |>
  ggplot(aes(x = year, y = rev_total_pp, color = type)) +
  geom_line(linewidth = 1.2) +
  scale_x_continuous(breaks = seq(2013, 2023, 2)) +
  scale_y_continuous(labels = scales::label_dollar()) +
  labs(
    title = paste("Per-Pupil Revenue:", district_sample),
    x = "Year",
    y = "Revenue per Pupil",
    color = "CPI Adjustment"
  ) +
  theme_minimal()
```

## Best practices

1. **Use inflation adjustment for multi-year analyses**: Comparing nominal dollars across years can be misleading.

2. **Be consistent with your base year**: Use the same `cpi_adj` value for all data in an analysis.

3. **Document your choice**: Always note whether values are nominal or real, and which base year you used.

4. **Consider your audience**: Current dollars (most recent year) are often most intuitive for general audiences.

## Technical notes

- The CPI data comes from the U.S. Bureau of Labor Statistics CPI-U series.
- School year alignment ensures the index matches the academic calendar.
- Total and per-pupil columns are scaled by the same `cpi_adj_index`, so adjusted per-pupil values equal adjusted totals divided by enrollment.
- The `cpi_sy12` column is always included regardless of adjustment choice.
- If the `cpi_adj` baseline year falls outside the requested `yr` range, that year's file is downloaded to source the baseline and then dropped from the returned data.

## See also

- The "Basic usage of edfinr" vignette for an overview of `get_finance_data()`.
- On the package website: the "CWIFT" article for adjusting across *places* rather than years, and the "Capital and Facilities" article for the flows-vs-stocks distinction in practice.
