Overview

Row

Total by Offence Division

Total Offences by Year Ending

Row

Average Crime Rate per 100,000 People Over Time

Subdivisions

Row

Top 10 Subdivisions

Top 10 Offence Subgroups

Crime Rate

Row

Rate per 100k by Division

Top 10 Subgroups by Rate


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

---
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