Crime Statistics Agency. (2025). Recorded Offences Visualisation Year Ending 2024. Crime Statistics Agency. https://files.crimestatistics.vic.gov.au/2025-03/Data_Tables_Recorded_Offences_Visualisation_Year_Ending_December_2024.xlsx
---
title: 'How Safe Are Your Suburbs? A Students Guide to Crime Trends in Victoria'
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
social: menu
source_code: embed
html_document:
df_print: paged
---
```{r setup, include=FALSE}
library(flexdashboard)
library(tidyverse)
library(plotly)
library(DT)
library(RColorBrewer)
library(dplyr)
theme_set(theme_minimal())
```
```{r, include=FALSE}
my_colors <- c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
"#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf")
file_path <- "C:/Users/mrp68/Downloads/Data_Tables_Recorded_Offences_Visualisation_Year_Ending_December_2024.xlsx"
if (file.exists(file_path)) {
tryCatch({
raw_data <- read_excel(file_path, sheet = "Table 01", skip = 6)
colnames(raw_data) <- c("year", "year_ending", "offence_division",
"offence_subdivision", "offence_subgroup",
"recorded_offences", "rate_per_100k")
crime_data <- raw_data %>%
filter(!is.na(recorded_offences)) %>%
mutate(across(c(recorded_offences, rate_per_100k), as.numeric)) %>%
clean_names()
student_crime_data <- crime_data %>%
filter(offence_division %in% c(
"A Crimes against the person",
"B Property and deception offences",
"H Public order and security offences",
"E Justice procedures offences"
))
}, error = function(e) {
message("Error loading or cleaning data from the Excel file at ", file_path, ".")
message("Original R error message: ", e$message)
student_crime_data <<- data.frame(
year = rep(2020:2024, each = 50),
year_ending = rep(paste0("31-Dec-", 2020:2024), each = 50),
offence_division = sample(c("A Crimes against the person", "B Property and deception offences",
"H Public order and security offences", "E Justice procedures offences"), 250, replace = TRUE),
offence_subdivision = sample(c("Assault", "Theft", "Weapons", "Breach of Order"), 250, replace = TRUE),
offence_subgroup = sample(c("Common Assault", "Stealing", "Firearm Offences", "Breach of Bail Conditions"), 250, replace = TRUE),
recorded_offences = sample(100:5000, 250, replace = TRUE),
rate_per_100k = sample(10:500, 250, replace = TRUE)
)
})
} else {
stop("Error: Excel file not found at the specified path: ", file_path)
}
```
Overview
=======================================================================
Row
-----------------------------------------------------------------------
### Total by Offence Division
```{r}
summary_by_division <- student_crime_data %>%
group_by(offence_division) %>%
summarise(total = sum(recorded_offences, na.rm = TRUE))
ggplotly(
ggplot(summary_by_division, aes(x = reorder(offence_division, total), y = total)) +
geom_col(fill = my_colors[1]) +
coord_flip() +
labs(title = "Total Offences by Division", x = "Offence Division", y = "Total Offences") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
axis.text.y = element_text(size = 10),
axis.text.x = element_text(size = 10),
axis.title = element_text(size = 12))
)
```
### Total Offences by Year Ending
```{r}
summary_by_year <- student_crime_data %>%
group_by(year_ending) %>%
summarise(total = sum(recorded_offences, na.rm = TRUE))
ggplotly(
ggplot(summary_by_year, aes(x = year_ending, y = total)) +
geom_col(fill = my_colors[2]) +
labs(title = "Total Offences by Year Ending", x = "Year", y = "Total Offences") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1, size = 10),
axis.text.y = element_text(size = 10),
axis.title = element_text(size = 12))
)
```
Row
-----------------------------------------------------------------------
### Average Crime Rate per 100,000 People Over Time
```{r}
rate_by_year <- student_crime_data %>%
group_by(year_ending) %>%
summarise(avg_rate_per_100k = mean(rate_per_100k, na.rm = TRUE)) %>%
arrange(year_ending)
ggplotly(
ggplot(rate_by_year, aes(x = year_ending, y = avg_rate_per_100k, group = 1)) +
geom_line(color = my_colors[7], size = 1.2) +
geom_point(color = my_colors[7], size = 3, shape = 21, fill = "white", stroke = 1) +
labs(title = "Average Crime Rate per 100,000 People Over Time",
x = "Year Ending",
y = "Average Rate per 100k") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1, size = 10),
axis.text.y = element_text(size = 10),
axis.title = element_text(size = 12))
)
```
Subdivisions
=======================================================================
Row {data-height=100}
-----------------------------------------------------------------------
### Top 10 Subdivisions
```{r}
top_subdivisions <- student_crime_data %>%
group_by(offence_subdivision) %>%
summarise(total = sum(recorded_offences)) %>%
slice_max(total, n = 10)
ggplotly(
ggplot(top_subdivisions, aes(x = reorder(offence_subdivision, total), y = total)) +
geom_col(fill = my_colors[3]) +
coord_flip() +
labs(title = "Top 10 Offence Subdivisions", x = "Subdivision", y = "Total Offences") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
axis.text.y = element_text(size = 10),
axis.text.x = element_text(size = 10),
axis.title = element_text(size = 12))
)
```
### Top 10 Offence Subgroups
```{r}
top_subgroups <- student_crime_data %>%
group_by(offence_subgroup) %>%
summarise(total = sum(recorded_offences)) %>%
arrange(desc(total)) %>%
slice(1:10)
ggplotly(
ggplot(top_subgroups, aes(x = reorder(offence_subgroup, total), y = total)) +
geom_col(fill = my_colors[4]) +
coord_flip() +
labs(title = "Top 10 Offence Subgroups", x = "Offence Subgroup", y = "Total Offences") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
axis.text.y = element_text(size = 10),
axis.text.x = element_text(size = 10),
axis.title = element_text(size = 12))
)
```
Crime Rate
=======================================================================
Row
-----------------------------------------------------------------------
### Rate per 100k by Division
```{r}
rate_summary <- student_crime_data %>%
group_by(offence_division) %>%
summarise(avg_rate = mean(rate_per_100k, na.rm = TRUE))
ggplotly(
ggplot(rate_summary, aes(x = reorder(offence_division, avg_rate), y = avg_rate)) +
geom_col(fill = my_colors[5]) +
coord_flip() +
labs(title = "Average Crime Rate per 100,000 People", x = "Division", y = "Rate") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
axis.text.y = element_text(size = 10),
axis.text.x = element_text(size = 10),
axis.title = element_text(size = 12))
)
```
### Top 10 Subgroups by Rate
```{r}
top_rate_subgroups <- student_crime_data %>%
group_by(offence_subgroup) %>%
summarise(avg_rate = mean(rate_per_100k, na.rm = TRUE)) %>%
arrange(desc(avg_rate)) %>%
slice(1:10)
ggplotly(
ggplot(top_rate_subgroups, aes(x = reorder(offence_subgroup, avg_rate), y = avg_rate)) +
geom_col(fill = my_colors[6]) +
coord_flip() +
labs(title = "Top 10 Subgroups by Crime Rate", x = "Offence Subgroup", y = "Rate per 100k") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
axis.text.y = element_text(size = 10),
axis.text.x = element_text(size = 10),
axis.title = element_text(size = 12))
)
```
-----------------------------------------------------------------------
### Reference
Crime Statistics Agency. (2025). Recorded Offences Visualisation Year Ending 2024. Crime Statistics Agency. https://files.crimestatistics.vic.gov.au/2025-03/Data_Tables_Recorded_Offences_Visualisation_Year_Ending_December_2024.xlsx