Do prices feel like they are rising more than the CPI (Consumer Price Index) says? Yes.
For 2025, the overall CPI increased by a fairly modest 2.7% (CPI-U for all urban consumers, December to December). The CPI measures the change in price of a basket of goods across eight major categories: food and beverages, housing, clothing, transportation, medical care, recreation, education and communications, and others, across a wide range of metropolitan statistical areas (MSA). Each month, Bureau of Labor Statistics data collectors collect approximately 94,000 awards. For some items, prices are adjusted to eliminate the effect of a change in quality (for example, today’s Toyota Corolla is a very different car than it was ten years ago). There are separate indexes for more than 200 items nationwide, and separate indexes for the eight major categories by MSA.
What matters, of course, are the price changes of the items you buy, especially those you buy frequently, such as food. Each individual item has its own reasons for the price changes – egg prices are affected by bird flu, coffee prices are affected by weather and geopolitical conditions in other countries, etc. These factors are beyond our control.
I was interested in comparing food price changes for commonly used items. This is based on CPIs for national data in categories such as eggs. Of course, I don’t measure YOUR specific egg purchase (such as store brand, organic, medium, white, 12 count, at CTown in Intercourse, Pennsylvania).
I started with the December 11 values of ten individual food categories and also the overall CPI-U, seasonally adjusted. The values I used are as follows (although I understand that values change as there are changes in seasonal adjustment factors, weights, etc.)
For comparison purposes, I set all eleven indices in 2015 to an index value of 100 and plotted them on a line graph. The value of each year is now relative to 2015.
Over a ten-year period, ground beef, eggs and lettuce are higher than the overall CPI. These three food indices have seen a lot of volatility. The pandemic year 2022 was the year of the largest increase for many foods. Interestingly enough, apple prices have dropped!
Another way to look at this is to look at bar charts of percentage changes. Here are graphs showing percentage changes from 2015 to 2025, 2024 to 2025 and 2021 to 2022:
Before 2025, compared to 2015, I didn’t know how much prices had increased for ground beef, lettuce and eggs.
For 2025, the price increase for ground beef, eggs and coffee compared to 2024 has been much larger than the total increase in the CPI of 2.7%. This probably comes as no surprise if you’re the household member doing the grocery shopping.
For 2022 versus 2021, the increase in all foods except ground beef exceeded the overall CPI. We probably remember this during the years of the Covid pandemic.
In the insurance world, the goods and services that insurance pays for have also increased more than the overall CPI. For example, medical care costs, vehicle maintenance and repair costs, and construction and repair costs have consistently exceeded the overall CPI. So don’t be surprised if prices for health insurance, car insurance and home insurance continue to rise.
Here is the R code:
library(readxl)
library(dplyr)
library(tidyr)
library(ggplot2)
df <- read_excel("C:/Users/Jerry/Desktop/R_files/CPI_10_years.xlsx")
print(df, n = Inf, width = Inf)
# 1. Convert data to 'long' format for easier plotting
df_long <- df %>%
pivot_longer(cols = -Year, names_to = "Category", values_to = "Index")
# 2. Re-base every category so 2015 = 100
df_normalized <- df_long %>%
group_by(Category) %>%
mutate(Index_100 = (Index / Index[Year == 2015]) * 100) %>%
ungroup()
# 3. Plot line graph "Race to the Top"
ggplot(df_normalized, aes(x = Year, y = Index_100, color = Category)) +
geom_line(aes(size = Category == "Overall CPI"), show.legend = FALSE) +
# Use subset to only label the last point (2025)
geom_text(data = subset(df_normalized, Year == 2025),
aes(label = Category),
hjust = -0.1, # Push text to the right of the point
size = 4, fontface="bold",
show.legend = FALSE) +
# Fix X-Axis: No decimals, every year labeled
scale_x_continuous(breaks = seq(2015, 2025, 1), limits = c(2015, 2027)) +
# Highlight the Overall CPI in black/thicker line
scale_size_manual(values = c("TRUE" = 2.0, "FALSE" = 0.8)) +
scale_color_manual(values = c("Overall CPI" = "black",
"Eggs" = "red",
"Ground Beef" = "darkred",
"Apples" = "forestgreen",
"Milk" = "blue",
"Bread" = "orange",
"Coffee" = "brown",
"Lettuce" = "lightgreen",
"Soup" = "#008080",
"Breakfast Cereal" = "purple",
"Other Fresh Veg" = "gray")) +
theme_minimal() +
theme(
legend.position = "none", # Remove legend
plot.title = element_text(face = "bold", size = 16),
axis.title = element_text(face = "bold"),
axis.text = element_text(face = "bold"),
plot.margin = margin(r = 100), # Add space on the right for labels
panel.grid.minor = element_blank()
) +
coord_cartesian(clip = 'off') + # Prevent labels from being cut off
labs(title = "Cumulative Food Price Changes (2015 = 100)",
subtitle = "Food categories vs. Overall CPI Baseline",
y = "Index (2015 = 100)",
x = "Year")
#4 Plot bar graph with % changes
# filter data for start and end years
plot_cpi_change <- function(data, start_yr, end_yr) {
# 1. Prepare dynamic column names for the mutation step
start_col <- paste0("Yr", start_yr)
end_col <- paste0("Yr", end_yr)
# 2. Data Processing
df_bar <- data %>%
filter(Year %in% c(start_yr, end_yr)) %>%
pivot_longer(cols = -Year, names_to = "Category", values_to = "Index") %>%
pivot_wider(names_from = Year, names_prefix = "Yr", values_from = Index) %>%
# Use .data[[]] to dynamically reference the columns created by pivot_wider
mutate(Pct_Change = ((.data[[end_col]] - .data[[start_col]]) / .data[[start_col]]) * 100) %>%
mutate(Category = reorder(Category, -Pct_Change))
# 3. Visualization
ggplot(df_bar, aes(x = Category, y = Pct_Change, fill = Category)) +
geom_bar(stat = "identity", color = "black", size = 0.5) +
# Logic for text placement based on positive/negative change
geom_text(aes(label = paste0(round(Pct_Change, 1), "%"),
vjust = ifelse(Pct_Change >= 0, -0.5, 1.5)),
fontface = "bold", size = 4.5) +
scale_fill_manual(values = c("Overall CPI" = "black", "Soup" = "#008080", "Eggs" = "red",
"Ground Beef" = "darkred", "Apples" = "forestgreen", "Milk" = "blue",
"Bread" = "orange", "Coffee" = "brown", "Lettuce" = "lightgreen",
"Breakfast Cereal" = "purple", "Other Fresh Veg" = "gray")) +
theme_minimal() +
theme(legend.position = "none",
plot.title = element_text(face = "bold", size = 18, hjust = 0.5),
axis.title = element_text(face = "bold", size = 14),
axis.text.x = element_text(face = "bold", size = 11, angle = 45, hjust = 1),
axis.text.y = element_text(face = "bold", size = 11),
panel.grid.major.x = element_blank()) +
coord_cartesian(clip = 'off') +
labs(title = paste("CPI FOOD PRICE CHANGES (", start_yr, "TO", end_yr, ")"),
y = "PERCENT CHANGE (%)", x = "CATEGORY")
}
plot_cpi_change(df, 2015, 2025)
plot_cpi_change(df, 2024, 2025)
plot_cpi_change(df, 2021, 2022)
End
#prices #feel #rising #CPI #bloggers


