CPI revisions look small in absolute terms but matter materially for inflation-targeting central banks. The Federal Reserve targets PCE; markets focus on CPI; the BLS revises seasonal factors annually. A nowcast or policy narrative built on revised numbers can look very different from the same narrative built on the data that was actually available at the time.
This vignette uses fred_real_time_panel() to track how
core inflation estimates have evolved across vintages, and
fred_vintage_revisions() to quantify the revision behaviour
of headline series.
The chunks below require an API key.
The simple comparison most analysts start with: headline CPI vs core CPI (food and energy excluded), as we see them today.
inflation_now <- fred_series(
c("CPIAUCSL", "CPILFESL"),
from = "2018-01-01",
transform = "yoy_pct",
format = "wide"
)
plot(inflation_now, ylab = "% YoY",
main = "Headline vs core CPI, latest vintage")This is what shows up in most papers. But the actual story policymakers saw at each FOMC meeting is closer to the first-release values.
Use fred_first_release() to get the value that was
published at each release date, with no subsequent revisions:
core_first <- fred_first_release(
"CPILFESL",
from = "2018-01-01",
units = "pc1" # YoY percent change
)
core_latest <- fred_series(
"CPILFESL",
from = "2018-01-01",
transform = "yoy_pct"
)
# Plot both on one chart
plot(core_first$date, core_first$value, type = "l",
xlab = "", ylab = "% YoY",
main = "Core CPI: first release vs latest vintage",
ylim = range(c(core_first$value, core_latest$value), na.rm = TRUE))
graphics::lines(core_latest$date, core_latest$value, col = "tomato")
graphics::legend("topleft",
legend = c("First release", "Latest vintage"),
col = c("black", "tomato"), lty = 1, bty = "n")The two lines diverge meaningfully across pivot points (early 2022, late 2023). That divergence is the data revision.
Pull a panel of core CPI as it was seen on each FOMC SEP meeting in 2024. This is the data that informed Summary of Economic Projections forecasts.
panel <- fred_real_time_panel(
"CPILFESL",
vintages = sep_meetings$date,
from = "2022-01-01"
)
head(panel)The realtime_start column tells you which vintage each
row belongs to. To visualise the four lines:
panel_wide <- stats::reshape(
panel[, c("date", "value", "realtime_start")],
idvar = "date", timevar = "realtime_start",
direction = "wide"
)
names(panel_wide) <- sub("^value\\.", "v", names(panel_wide))
panel_wide <- panel_wide[order(panel_wide$date), ]
cols <- c("#1F77B4", "#FF7F0E", "#2CA02C", "#D62728")
plot(panel_wide$date, panel_wide[[2]], type = "l", col = cols[1],
ylim = range(unlist(panel_wide[, -1]), na.rm = TRUE),
xlab = "", ylab = "Core CPI level",
main = "Core CPI as seen at four 2024 SEP meetings")
for (i in 3:ncol(panel_wide)) {
graphics::lines(panel_wide$date, panel_wide[[i]], col = cols[i - 1L])
}
graphics::legend("topleft",
legend = format(sep_meetings$date, "%b %Y"),
col = cols, lty = 1, bty = "n", cex = 0.8)The vintage panel makes it visually obvious where revisions accumulated.
For a research-grade summary, use
fred_vintage_revisions():
rev <- fred_vintage_revisions("CPILFESL", from = "2020-01-01")
head(rev)
summary(rev$revision_total_pct)The output gives, per observation date: how many vintages exist, the first and final value, total revision (in level and percent), mean and SD of inter-vintage revisions, and elapsed days from first publication to final.
Use it to:
revision_sd).Pin the vintage in your citation, so a reviewer in 2027 sees the same data:
fred_cite_series(
"CPILFESL",
vintage_date = "2024-12-18",
format = "bibtex"
)
#> [1] "@misc{FRED_CPILFESL_2024,\n title = {CPILFESL [CPILFESL]},\n author = {{Federal Reserve Bank of St. Louis}},\n publisher = {Federal Reserve Bank of St. Louis},\n year = {2024},\n url = {https://fred.stlouisfed.org/series/CPILFESL},\n urldate = {2024-12-18},\n note = {FRED, Federal Reserve Bank of St. Louis}\n}"vignette("nowcasting-with-fred") for using vintages in
a nowcasting backtest.vignette("multi-series-workflows") for the basic
fetch/transform/plot pattern.