By Rahul Pannu [S4029345]
Australia’s cost-of-living crisis has emerged as a major concern in recent years, driven by sharp increases in the prices of essential goods and services. Inflation surged to multi-decade highs during 2022–23, significantly straining household budgets [ABS]. By the March quarter 2025, inflation has eased to 2.4% annually — back within the Reserve Bank’s target range of 2–3% — but this moderation masks substantial variation across spending categories [ABS].
In this report, we analyse official Consumer Price Index (CPI) data from the Australian Bureau of Statistics (ABS) for the March quarter 2025. We focus on five key categories that shape everyday living costs:
Housing (rents and new dwellings),
Food and non-alcoholic beverages,
Electricity,
Education, and
Transport.
Through a series of targeted visualisations, we explore both quarterly spikes and annual trends, providing a clearer picture of where cost pressures are most intense. This analysis is intended for a general audience and policymakers, translating raw CPI data into meaningful insights on how Australians are being affected — and where policy interventions may already be having an impact.
This project aims to tell a data-driven story about the cost-of-living crisis in Australia through:
The analysis uses data published in March Quarter 2025 to provide timely insights for public discourse and policy engagement.
Data Source:
The analysis is based on publicly available CPI datasets from the Australian Bureau of Statistics (ABS), using data up to the March Quarter 2025.
library(tidyverse)
# Set working directory if needed
# setwd("your-path-to-files")
# Load all CSVs
cpi_trimmed <- read_csv("All groups CPI and Trimmed mean, Australia, annual movement (%).csv", skip = 1)
cpi_quarterly <- read_csv("All groups CPI, Australia, quarterly and annual movement (%).csv", skip = 1)
goods_services <- read_csv("CPI, Goods and Services components, annual movement (%).csv", skip = 1)
education <- read_csv("Education, Australia, March quarter movements (%).csv", skip = 1)
electricity <- read_csv("Electricity Index, Australia (June 2023 quarter = 100.0).csv", skip = 1)
grocery <- read_csv("Grocery products, annual movement (%).csv", skip = 1)
insurance <- read_csv("Insurance, Australia, quarterly and annual movement (%).csv", skip = 1)
new_dwellings <- read_csv("New dwellings, quarterly and annual movement (%).csv", skip = 1)
rents <- read_csv("Rents, Australia, quarterly and annual movement (%).csv", skip = 1)
services <- read_csv("Selected services annual movements (%).csv", skip = 1)
Goal: Show how headline and underlying (trimmed mean) inflation evolved over time.
library(tidyverse)
library(lubridate)
library(zoo)
# Clean and reshape CPI trimmed dataset
cpi_trimmed <- cpi_trimmed %>%
rename(Date = 1, Headline_CPI = 2, Trimmed_Mean = 3) %>%
mutate(Date = zoo::as.yearqtr(Date, format = "%b-%y")) %>%
pivot_longer(cols = c(Headline_CPI, Trimmed_Mean),
names_to = "Type", values_to = "Inflation")
# Plot
ggplot(cpi_trimmed, aes(x = Date, y = Inflation, color = Type)) +
geom_line(size = 1.2) +
labs(title = "Annual Inflation: Headline vs Trimmed Mean CPI",
x = "Year", y = "Inflation (%)") +
theme_minimal()
Goal: Compare annual inflation trends between goods and services over the past decade.
goods_services <- goods_services %>%
rename(Date = 1, Goods = 2, Services = 3) %>%
mutate(Date = zoo::as.yearqtr(Date, format = "%b-%y")) %>%
pivot_longer(cols = c(Goods, Services), names_to = "Type", values_to = "Annual_Change")
ggplot(goods_services, aes(x = Date, y = Annual_Change, color = Type)) +
geom_line(size = 1.2) +
labs(title = "Goods vs Services Inflation (Annual %)",
x = "Date", y = "Annual % Change") +
theme_minimal()
## Warning: Removed 4 rows containing missing values or values outside the scale range
## (`geom_line()`).
Goal: To identify the key drivers of inflation in the March 2025 quarter by highlighting the top categories with the highest annual percentage increases. This visual isolates the most inflationary service sectors, such as insurance, pet services, and education, which are contributing disproportionately to the cost-of-living pressure.
library(tidyverse)
# Step 1: Load with correct header row
services_raw <- read_csv("Selected services annual movements (%).csv", skip = 2)
# Step 2: Rename columns manually
colnames(services_raw) <- c("Category", "Mar_24", "Jun_24", "Sep_24", "Dec_24", "Mar_25")
# Step 3: Drop NA or footer rows (like "Source")
services_clean <- services_raw %>%
filter(!is.na(Category), !str_detect(Category, "Source"))
# Step 4: Get top 10 contributors by Mar 2025
top_mar25 <- services_clean %>%
arrange(desc(Mar_25)) %>%
slice(1:10)
# Step 5: Plot
ggplot(top_mar25, aes(x = reorder(Category, Mar_25), y = Mar_25)) +
geom_bar(stat = "identity", fill = "#4682B4") +
coord_flip() +
labs(
title = "Top CPI Contributors (Annual % Change – Mar 2025)",
subtitle = "Selected Services Categories",
x = "Category",
y = "Annual % Change"
) +
theme_minimal(base_size = 8)
Goal: Track how inflation in selected services categories has evolved over the past year.
services_long <- services %>%
rename(Category = 1) %>%
pivot_longer(-Category, names_to = "Quarter", values_to = "Change") %>%
mutate(Quarter = zoo::as.yearqtr(Quarter, format = "%b-%y"))
ggplot(services_long, aes(x = Quarter, y = Change, color = Category)) +
geom_line(size = 1.1) +
labs(title = "Trends in Services Inflation by Category",
x = "Quarter", y = "Annual % Change") +
theme_minimal()
Goal: Track annual price changes in grocery items — a major driver of household cost pressures.
grocery_clean <- grocery %>%
rename(Category = 1) %>%
pivot_longer(-Category, names_to = "Quarter", values_to = "Annual_Change") %>%
mutate(Quarter = zoo::as.yearqtr(Quarter, format = "%b-%y"))
ggplot(grocery_clean, aes(x = Quarter, y = Annual_Change, color = Category)) +
geom_line(size = 1.1) +
labs(
title = "Annual Price Change in Grocery Items",
subtitle = "Selected food and non-alcoholic beverage categories",
x = "Quarter",
y = "Annual % Change"
) +
theme_minimal()
Goal: To show the impact of government electricity rebates on household electricity costs by comparing index values with and without rebates. The visual captures how policy interventions, like the Energy Bill Relief Fund (EBRF), helped cushion electricity price rises, especially across key quarters in 2023–25.
library(tidyverse)
library(lubridate)
colnames(electricity) <- c("Quarter", "Excluding_Rebates", "Including_Rebates")
# Convert Quarter to proper date
electricity <- electricity %>%
filter(!is.na(Quarter)) %>%
mutate(
Quarter = as.Date(as.yearqtr(Quarter, format = "%b-%y"))
) %>%
pivot_longer(cols = c(Excluding_Rebates, Including_Rebates),
names_to = "Rebate_Type", values_to = "Index")
ggplot(electricity, aes(x = Quarter, y = Index, color = Rebate_Type)) +
geom_line(size = 1.3) +
geom_point(size = 2) +
labs(
title = "Electricity Index (June 2023 = 100)",
subtitle = "Showing effect of Government Rebates on Electricity Prices",
x = "Quarter",
y = "Index Value",
color = "Index Type"
) +
scale_color_manual(
values = c("Excluding_Rebates" = "#D55E00", "Including_Rebates" = "#0072B2"),
labels = c("Excluding Government Rebates", "Including Government Rebates")
) +
theme_minimal(base_size = 13)
## Warning: Removed 16 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Warning: Removed 16 rows containing missing values or values outside the scale range
## (`geom_point()`).
Goal: To track quarterly price changes in rents and new dwelling purchases, highlighting housing-related cost pressures faced by Australian households. This visual helps uncover differences between the rental market and homeownership costs, and shows how housing inflation has evolved over recent quarters — a critical component of the broader cost-of-living narrative.
rents <- rents %>%
rename(Date = 1, Rents = 2) %>%
mutate(Date = zoo::as.yearqtr(Date, format = "%b-%y"))
new_dwellings <- new_dwellings %>%
rename(Date = 1, New_Dwellings = 2) %>%
mutate(Date = zoo::as.yearqtr(Date, format = "%b-%y"))
housing <- full_join(rents, new_dwellings, by = "Date") %>%
pivot_longer(cols = c(Rents, New_Dwellings), names_to = "Source", values_to = "Change")
ggplot(housing, aes(x = Date, y = Change, color = Source)) +
geom_line(size = 1.1) +
labs(title = "Quarterly Price Movement: Housing",
x = "Date", y = "Quarterly % Change") +
theme_minimal()
## Warning: Removed 8 rows containing missing values or values outside the scale range
## (`geom_line()`).
Goal: Visualise key cost changes in two significant non-discretionary service areas: education and insurance.
library(tidyverse)
library(zoo)
# --- Load and clean Education ---
education <- education %>%
rename(Date = 1, Education = 5) %>% # Total Education (%)
mutate(Date = zoo::as.yearqtr(Date, format = "%b-%y"))
# --- Load and clean Insurance (March quarters only) ---
insurance <- insurance %>%
rename(Date = 1, Quarterly_Change = 2, Insurance = 3) %>%
mutate(Date = zoo::as.yearqtr(Date, format = "%b-%y")) %>%
filter(format(Date, "%q") == "1") # Keep only Mar quarters
# --- Join the datasets ---
edu_ins <- full_join(education, insurance, by = "Date") %>%
drop_na()
# --- Pivot longer for plot ---
edu_ins_long <- edu_ins %>%
pivot_longer(cols = c(Education, Insurance),
names_to = "Category", values_to = "Change")
# --- Plot ---
ggplot(edu_ins_long, aes(x = Date, y = Change, color = Category)) +
geom_line(size = 1.2) +
geom_point(size = 2) +
labs(
title = "March Quarter Inflation: Education vs Insurance",
subtitle = "Annual percentage changes from ABS datasets (2019–2025)",
x = "Date",
y = "Annual % Change"
) +
theme_minimal()