Australian Bureau of Statistics. (2024). Regional population,
2023–24: Victoria (Catalogue No. 3218.0).
Australian Government.
https://www.abs.gov.au/statistics/people/population/regional-population/latest-release
Australian Bureau of Statistics. (2024). Age and sex
distribution, Victoria.
Australian Government Data Portal.
https://data.gov.au/dataset
The left chart compares population growth percentage-wise, while the right shows absolute increases. Together, they reveal that outer-metropolitan LGAs such as Melton, Wyndham, and Casey lead both in relative and total growth, reflecting Victoria’s ongoing suburban expansion.
The chart shows that Melbourne consistently maintains a slightly
higher female population share across most age groups compared to the
rest of Victoria.
The largest difference is seen among younger working-age groups (25–34
years), reflecting Melbourne’s attraction for education and job
opportunities.
Meanwhile, the Rest of Victoria records higher female shares in older
age brackets, suggesting an aging regional demographic trend.
---
title: "Victoria Population Growth & Demographic Shifts (2023–24)"
author: "Albert Shaji (S4140500)"
date: "`r format(Sys.Date())`"
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: fill
theme: cosmo
source_code: embed
---
```{r data_global, include=FALSE}
suppressPackageStartupMessages({
library(tidyverse); library(readxl); library(janitor); library(scales); library(stringr); library(flexdashboard)
})
abs_xlsx <- "32180DS0002_2023-24.xlsx"
vic_sheet <- "Table 2"
raw <- read_excel(abs_xlsx, sheet = vic_sheet, col_names = FALSE)
# Find header row
hdr_row <- which(apply(raw, 1, function(r) any(grepl("LGA", as.character(r), ignore.case = TRUE))))[1]
if (is.na(hdr_row)) hdr_row <- 6
headers <- unlist(raw[hdr_row, ], use.names = FALSE)
abs_vic0 <- as_tibble(raw[(hdr_row + 1):nrow(raw), , drop = FALSE])
names(abs_vic0) <- make_clean_names(headers)
nm <- names(abs_vic0)
# LGA column
lga_col <- nm[grepl("(^lga$|^lga_?name|lga.*name)", nm, ignore.case = TRUE)][1]
if (is.na(lga_col)) {
nonnum_idx <- which(sapply(abs_vic0, function(x) any(grepl("[A-Za-z]", as.character(x)))))[1]
lga_col <- if (!is.na(nonnum_idx)) nm[nonnum_idx] else nm[min(2, length(nm))]
}
# ERP columns
erp23_col <- if ("no" %in% nm) "no" else if ("no_3" %in% nm) "no_3" else NA_character_
erp24_col <- if ("no_2" %in% nm) "no_2" else if ("no_4" %in% nm) "no_4" else NA_character_
if (is.na(erp23_col) || is.na(erp24_col)) {
cand <- nm[!grepl("code|name|percent|per_cent|km2|density|area|note", nm, TRUE)]
cand <- cand[sapply(abs_vic0[cand], function(x){
y <- suppressWarnings(as.numeric(gsub("[^0-9.-]", "", as.character(x))))
mean(!is.na(y)) > 0.6
})]
after_lga_idx <- match(lga_col, nm)
cand <- cand[match(cand, nm) > after_lga_idx]
if (length(cand) >= 2) { erp23_col <- cand[1]; erp24_col <- cand[2] }
}
num <- function(x) suppressWarnings(as.numeric(gsub("[^0-9.-]", "", as.character(x))))
abs_vic <- abs_vic0 |>
transmute(
lga = str_squish(as.character(.data[[lga_col]])),
erp_2023 = num(.data[[erp23_col]]),
erp_2024 = num(.data[[erp24_col]])
) |>
filter(!is.na(lga), lga != "", !grepl("total|victoria", lga, TRUE),
!is.na(erp_2023), !is.na(erp_2024), erp_2023 > 1000, erp_2024 > 1000) |>
mutate(growth_n = erp_2024 - erp_2023,
growth_pct = if_else(erp_2023 > 0, 100 * (erp_2024 - erp_2023) / erp_2023, NA_real_)) |>
arrange(desc(growth_pct))
# KPIs used by valueBox()
total_pop_2024 <- sum(abs_vic$erp_2024, na.rm = TRUE)
avg_growth_pct <- mean(abs_vic$growth_pct, na.rm = TRUE)
top_lga <- abs_vic$lga[which.max(abs_vic$growth_pct)]
demo_long <- NULL
demo_csv <- "Age and sex distribution, Victoria.csv"
if (file.exists(demo_csv)) {
library(readr); library(janitor); library(stringr); library(dplyr); library(tidyr)
demo_raw <- read_csv(demo_csv, skip = 1, show_col_types = FALSE) |> clean_names()
cols <- names(demo_raw)
# detect columns robustly
age_col <- cols[str_detect(cols, regex("^age_?group", TRUE))][1]
melb_all <- cols[str_detect(cols, regex("melbourne", TRUE))]
rest_all <- cols[str_detect(cols, regex("rest.*(vic|victoria)", TRUE))]
pick_last <- function(x) if (length(x)) tail(x, 1) else NA_character_
melb_f <- pick_last(melb_all[str_detect(melb_all, regex("female", TRUE))])
rest_f <- pick_last(rest_all[str_detect(rest_all, regex("female", TRUE))])
if (is.na(melb_f) && length(melb_all) >= 2) melb_f <- melb_all[2]
if (is.na(rest_f) && length(rest_all) >= 2) rest_f <- rest_all[2]
num <- function(x) suppressWarnings(as.numeric(gsub("[^0-9.-]", "", as.character(x))))
if (!is.na(age_col) && !is.na(melb_f) && !is.na(rest_f)) {
demo_long <- demo_raw |>
transmute(
age_group = .data[[age_col]],
Melbourne = num(.data[[melb_f]]),
`Rest of Vic`= num(.data[[rest_f]])
) |>
pivot_longer(-age_group, names_to = "region", values_to = "female_pct") |>
filter(!is.na(female_pct))
}
}
```
# Overview
## Victoria at a Glance {data-height=140} <!-- compact tile row -->
### KPIs
```{r}
valueBox(
value = paste0(formatC(total_pop_2024, big.mark = ",", format = "f", digits = 0),
" +", round(avg_growth_pct, 2), "% ", top_lga),
caption = "Total Population (2024)",
color = "primary"
)
```
## Interpretation
### 📝 Interpretation
- **Population Milestone** — Victoria’s population reached **`r scales::comma(total_pop_2024)`** in 2024, reflecting continued recovery and strong migration inflows post-pandemic.
- **Sustained Growth** — The state recorded an average growth rate of **`r round(avg_growth_pct, 2)`%**, showing steady population expansion supported by both metropolitan and regional development.
- **Top Performer** — **`r top_lga`** emerged as the fastest-growing LGA, highlighting the ongoing suburban expansion trend in Melbourne’s outer growth corridors.
## References
### References:
<div style="background-color:#eef5fb; border-left:5px solid #0073e6; border-radius:8px; padding:15px 25px; margin-top:15px; font-size:15px; line-height:1.6;">
- Australian Bureau of Statistics. (2024). *Regional population, 2023–24: Victoria (Catalogue No. 3218.0).*
Australian Government.
[https://www.abs.gov.au/statistics/people/population/regional-population/latest-release](https://www.abs.gov.au/statistics/people/population/regional-population/latest-release)
- Australian Bureau of Statistics. (2024). *Age and sex distribution, Victoria.*
Australian Government Data Portal.
[https://data.gov.au/dataset](https://data.gov.au/dataset)
</div>
# Population Growth
Row {.columns-2 data-height=800}
-------------------------------------
### Top 10 LGAs by % Growth
```{r}
abs_vic |>
slice_max(growth_pct, n = 10) |>
ggplot(aes(x = reorder(lga, growth_pct), y = growth_pct)) +
geom_col(fill = "steelblue", width = 0.7) +
coord_flip() +
labs(x = NULL, y = "Growth (%)", title = "Top 10 LGAs by Population Growth (%)") +
scale_y_continuous(labels = scales::label_percent(accuracy = 0.1, scale = 1)) +
theme_minimal(base_size = 18) +
theme(
plot.title = element_text(face = "bold", size = 18, hjust = 0.5),
axis.text = element_text(size = 14),
axis.title = element_text(size = 14)
)
```
### Top 10 LGAs by Absolute Growth (people)
```{r}
abs_vic |>
slice_max(growth_n, n = 10) |>
ggplot(aes(x = reorder(lga, growth_n), y = growth_n)) +
geom_col(fill = "darkorange", width = 0.7) +
coord_flip() +
labs(x = NULL, y = "People added (2023 → 2024)", title = "Top 10 LGAs by Absolute Growth") +
scale_y_continuous(labels = scales::label_number(big.mark = ",")) +
theme_minimal(base_size = 18) +
theme(
plot.title = element_text(face = "bold", size = 18, hjust = 0.5),
axis.text = element_text(size = 14),
axis.title = element_text(size = 14)
)
```
## Interpretation
The left chart compares population growth percentage-wise, while the right shows absolute increases.
Together, they reveal that outer-metropolitan LGAs such as Melton, Wyndham, and Casey lead both in relative and total growth, reflecting Victoria’s ongoing suburban expansion.
# Demographics <!-- Page 3 -->
## Female Share by Age Group
### Chart
```{r fig.width=22, fig.height=10, fig.align='center'}
ggplot(demo_long, aes(x = age_group, y = female_pct, fill = region)) +
geom_col(position = "dodge", width = 0.7) +
geom_text(aes(label = paste0(round(female_pct, 1), "%")),
position = position_dodge(width = 0.7),
vjust = -0.25, size = 6, color = "black", fontface = "bold") +
labs(
title = "Female Share by Age Group: Melbourne vs Rest of Victoria",
x = "Age Group",
y = "Female Population (%)",
fill = ""
) +
scale_y_continuous(
labels = function(x) paste0(x, "%"),
expand = expansion(mult = c(0, 0.12))
) +
scale_fill_manual(values = c("Melbourne" = "#FF6F61", "Rest of Vic" = "#00BFC4")) +
theme_minimal(base_size = 24) +
theme(
plot.title = element_text(face = "bold", size = 28, hjust = 0.5),
axis.text.x = element_text(size = 18, angle = 45, hjust = 1),
axis.text.y = element_text(size = 18),
axis.title = element_text(size = 20, face = "bold"),
legend.position = "bottom",
legend.text = element_text(size = 18),
panel.grid.minor = element_blank()
)
```
## Interpretation
### Interpretation
The chart shows that Melbourne consistently maintains a slightly higher female population share across most age groups compared to the rest of Victoria.
The largest difference is seen among younger working-age groups (25–34 years), reflecting Melbourne’s attraction for education and job opportunities.
Meanwhile, the Rest of Victoria records higher female shares in older age brackets, suggesting an aging regional demographic trend.