# ---- Load data ---------------------------------------------------------------
# Crime Statistics Agency (2026), Victim Reports data tables, year ending June 2026.
# The file is read locally; if it is missing it is downloaded directly from the source.
data_file <- "Data_Tables_Victim_Reports_Visualisation_Year_Ending_June_2026.xlsx"
data_url  <- paste0("https://files.crimestatistics.vic.gov.au/2026-09/", data_file)
if (!file.exists(data_file)) download.file(data_url, data_file, mode = "wb")

t02 <- read_excel(data_file, sheet = "Table 02")  # victims by sex and age (counts + rates)
t04 <- read_excel(data_file, sheet = "Table 04")  # victims by sex, age and offence (counts only)

t02 <- t02 |>
  rename(year = Year, sex = Sex, age = `Age Group`,
         reports = `Victim Reports`, rate = `Rate per 100,000 population`) |>
  filter(sex %in% c("Females", "Males", "People"),
         !age %in% c("Total", "Organisations"))

t04 <- t04 |>
  rename(year = Year, sex = Sex, age = `Age Group`, division = `Offence Division`,
         offence = `Offence Subdivision`, reports = `Victim Reports`) |>
  filter(sex %in% c("Females", "Males", "People"),
         age != "Total", !grepl("Total", offence))

# ---- Pre-processing ----------------------------------------------------------
# 1. Back-calculate the population behind each Table 02 rate:
#      population = reports / rate x 100,000
# 2. Group the 5-year age groups into the wider bands used in Table 04 and sum
#    the populations, so the offence-level counts in Table 04 can also be
#    expressed as rates per 100,000 (removing the effect of population growth).
age_levels <- c("00-04 years", "05-09 years", "10-14 years", "15-17 years",
                "18-19 years", "20-24 years", "25-29 years", "30-34 years",
                "35-39 years", "40-44 years", "45-49 years", "50-54 years",
                "55-59 years", "60-64 years", "65-69 years", "70-74 years",
                "75 years and over")
band_levels <- c("0–17", "18–24", "25–34", "35–44", "45–54", "55–64", "65–74", "75+")

to_band <- function(age) {
  case_when(
    age %in% c("00-04 years", "05-09 years", "10-14 years", "15-17 years", "00-17 years") ~ "0–17",
    age %in% c("18-19 years", "20-24 years", "18-24 years") ~ "18–24",
    age %in% c("25-29 years", "30-34 years", "25-34 years") ~ "25–34",
    age %in% c("35-39 years", "40-44 years", "35-44 years") ~ "35–44",
    age %in% c("45-49 years", "50-54 years", "45-54 years") ~ "45–54",
    age %in% c("55-59 years", "60-64 years", "55-64 years") ~ "55–64",
    age %in% c("65-69 years", "70-74 years", "65-74 years") ~ "65–74",
    age == "75 years and over" ~ "75+"
  )
}

# Shorter, plain-English offence labels
tidy_offence <- function(x) {
  x <- trimws(gsub("[A-Z][0-9]{2} ", "", x))
  recode(x,
         "Assault and related offences" = "Assault",
         "Stalking, harassment and threatening behaviour" = "Stalking, harassment & threats",
         "Arson & Property damage" = "Arson & property damage",
         "Burglary/Break and enter" = "Burglary / break and enter",
         "Deception" = "Deception (fraud, scams)")
}

t02 <- t02 |>
  mutate(pop  = reports / rate * 1e5,
         age  = factor(age, levels = age_levels),
         band = factor(to_band(as.character(age)), levels = band_levels))

pop_band <- t02 |>
  group_by(year, sex, band) |>
  summarise(reports = sum(reports), pop = sum(pop), .groups = "drop") |>
  mutate(rate = reports / pop * 1e5)

# Offence-level rates by sex and age band
offence_rates <- t04 |>
  mutate(band = factor(to_band(age), levels = band_levels),
         offence = tidy_offence(offence)) |>
  group_by(year, sex, band, offence) |>
  summarise(reports = sum(reports), .groups = "drop") |>
  left_join(select(pop_band, year, sex, band, pop), by = c("year", "sex", "band")) |>
  mutate(rate = reports / pop * 1e5)
1 in 64
Victorians aged 75+ recorded as a crime victim in 2026, up from 1 in 79 in 2017
+23%
change in the 75+ victimisation rate since 2017, while 25–34 year olds changed -5%
×4.2
the rate at which Victorians aged 75+ are victims of deception (fraud and scams), 2026 vs 2017

Safer for most, not for them

Crime statistics are usually told through the lens of young people: young offenders, young victims, nights out gone wrong. On that front, the news in Victoria’s latest figures is mostly good. Over the decade to June 2026, the chance of being recorded as a victim of crime fell for most age groups under 50 (Crime Statistics Agency, 2026).

But one group moved the other way. Victorians in their fifties, sixties, seventies and beyond became steadily more likely to be victims. The number of Victorians aged 75 and over grew by about 38% over the same period, so this is a growing group facing a growing risk. The five charts below follow that story: where the gap opens, how it built up, what is driving it, the scam surge at its centre, and who it affects most.

How to explore: every chart is interactive. Hover for exact values, use the buttons and menus above each chart to switch views, click legend items to hide or show groups, and drag to zoom (double-click to reset). Open “View underlying data” under any chart to see the exact numbers behind it.

Chart 1: The line crosses at 50

This first chart sets up the whole story by comparing two snapshots taken ten years apart. Each row is a five-year age group. The hollow circle shows how many people in that group were recorded as victims of crime per 100,000 in 2017, the filled circle shows the same rate in 2026, and the line between them is blue where the rate fell and orange where it rose. Reading from top to bottom, a clear split appears. In 10 of the 11 age groups under 50, the rate fell; for people aged 25–29, for example, it dropped by 7%. From 50–54 onwards, every single age group rose, and people aged 70–74 were 18% more likely to be recorded as a victim in 2026 than in 2017. Young adults still have the highest rates overall, so older Victorians are not yet the most victimised group, but they are the only part of the population moving in the wrong direction. Use the buttons above the chart to switch between all people, women and men. The turning point at 50 holds for both sexes, and the rise is steeper for women: among 70–74 year olds, the rate rose 31% for women compared with 13% for men.

c1 <- t02 |>
  filter(year %in% c(2017, 2026)) |>
  select(sex, age, year, rate) |>
  pivot_wider(names_from = year, values_from = rate, names_prefix = "r") |>
  mutate(change = r2026 / r2017 - 1,
         dir    = ifelse(change >= 0, "Rate rose", "Rate fell"),
         tip    = paste0("<b>", age, "</b><br>2017: ", fmt(r2017), " per 100,000",
                         "<br>2026: ", fmt(r2026), " per 100,000",
                         "<br>Change: ", sgn(change), fmt(change * 100), "%"))

sex_views <- c(People = "all people", Females = "women", Males = "men")
first_older <- which(age_levels == "50-54 years") - 1
c1_title <- function(s) list(
  text = paste0("<b>Victimisation fell for most under-50s but rose for every age group from 50 up</b>",
                "<br><sup>Victim reports per 100,000 people, ", sex_views[[s]],
                ", Victoria, year ending June 2017 vs 2026</sup>"),
  x = 0, xanchor = "left", y = 0.97, yref = "container", yanchor = "top")

p1 <- plot_ly(); grp1 <- character()
for (s in names(sex_views)) {
  d <- filter(c1, sex == s)
  for (dd in c("Rate fell", "Rate rose")) {
    dsub <- filter(d, dir == dd)
    if (nrow(dsub) == 0) next
    p1 <- add_segments(p1, data = dsub, x = ~r2017, xend = ~r2026, y = ~age, yend = ~age,
                       name = dd, legendgroup = dd, visible = (s == "People"),
                       line = list(color = ifelse(dd == "Rate rose", col_rise, col_fall), width = 4),
                       text = ~tip, hoverinfo = "text")
    grp1 <- c(grp1, s)
  }
  p1 <- add_markers(p1, data = d, x = ~r2017, y = ~age, name = "2017", legendgroup = "2017",
                    visible = (s == "People"), text = ~tip, hoverinfo = "text",
                    marker = list(color = "white", size = 9, line = list(color = "#555555", width = 2)))
  p1 <- add_markers(p1, data = d, x = ~r2026, y = ~age, name = "2026", legendgroup = "2026",
                    visible = (s == "People"), text = ~tip, hoverinfo = "text",
                    marker = list(color = "#222222", size = 9))
  grp1 <- c(grp1, s, s)
}

buttons1 <- lapply(names(sex_views), function(s) {
  list(method = "update", label = c(People = "All people", Females = "Women", Males = "Men")[[s]],
       args = list(list(visible = grp1 == s), list(title = c1_title(s))))
})

p1 |>
  layout(
    title = c1_title("People"), font = font_main,
    xaxis = list(title = "Victim reports per 100,000 people", zeroline = FALSE, tickformat = ","),
    yaxis = list(title = "", categoryorder = "array", categoryarray = age_levels),
    shapes = list(list(type = "rect", xref = "paper", x0 = 0, x1 = 1,
                       y0 = first_older - 0.5, y1 = length(age_levels) - 0.5,
                       fillcolor = col_rise, opacity = 0.07, line = list(width = 0))),
    annotations = list(
      list(xref = "paper", x = 0.99, y = length(age_levels) - 1.3, xanchor = "right",
           text = "<b>Aged 50+:</b> every group up", showarrow = FALSE,
           font = list(color = col_rise, size = 13)),
      src_note("Crime Statistics Agency (2026), Victim Reports, Table 02.")),
    updatemenus = list(list(type = "buttons", direction = "right", buttons = buttons1,
                            x = 0, xanchor = "left", y = 1.02, yanchor = "bottom",
                            bgcolor = "#F4F4F4", bordercolor = "#BBBBBB")),
    legend = list(orientation = "h", x = 1, xanchor = "right", y = 1.02, yanchor = "bottom"),
    margin = list(t = 150, b = 110)
  ) |>
  tidy_config()

Chart description: a dumbbell chart of 17 age groups, with buttons to switch between all people, women and men. Each row joins the 2017 rate (hollow circle) to the 2026 rate (filled circle). In every view, the rows from 50–54 upwards are orange, meaning the rate rose; most rows for children and adults under 50 are blue, meaning the rate fell.

View underlying data
Victim reports per 100,000 people, by sex and age group (Table 02)
Group Age group Rate 2017 Rate 2026 Change
All people 00-04 years 238 142 -40%
All people 05-09 years 446 281 -37%
All people 10-14 years 1,267 1,175 -7%
All people 15-17 years 2,568 2,655 +3%
All people 18-19 years 4,120 3,923 -5%
All people 20-24 years 5,538 5,018 -9%
All people 25-29 years 5,960 5,535 -7%
All people 30-34 years 5,781 5,572 -4%
All people 35-39 years 5,516 5,340 -3%
All people 40-44 years 5,419 5,068 -6%
All people 45-49 years 5,037 4,885 -3%
All people 50-54 years 4,421 4,799 +9%
All people 55-59 years 3,664 4,126 +13%
All people 60-64 years 2,976 3,472 +17%
All people 65-69 years 2,422 2,808 +16%
All people 70-74 years 1,879 2,222 +18%
All people 75 years and over 1,259 1,551 +23%
Women 00-04 years 248 146 -41%
Women 05-09 years 429 271 -37%
Women 10-14 years 1,403 1,224 -13%
Women 15-17 years 2,948 2,738 -7%
Women 18-19 years 4,075 3,872 -5%
Women 20-24 years 5,403 4,775 -12%
Women 25-29 years 5,339 5,129 -4%
Women 30-34 years 4,968 5,094 +3%
Women 35-39 years 4,937 4,783 -3%
Women 40-44 years 4,834 4,493 -7%
Women 45-49 years 4,338 4,349 +0%
Women 50-54 years 3,598 4,162 +16%
Women 55-59 years 2,844 3,472 +22%
Women 60-64 years 2,159 2,715 +26%
Women 65-69 years 1,762 2,162 +23%
Women 70-74 years 1,361 1,777 +31%
Women 75 years and over 1,008 1,304 +29%
Men 00-04 years 228 139 -39%
Men 05-09 years 462 291 -37%
Men 10-14 years 1,138 1,125 -1%
Men 15-17 years 2,203 2,570 +17%
Men 18-19 years 4,160 3,963 -5%
Men 20-24 years 5,667 5,234 -8%
Men 25-29 years 6,581 5,925 -10%
Men 30-34 years 6,609 6,049 -8%
Men 35-39 years 6,098 5,906 -3%
Men 40-44 years 6,011 5,646 -6%
Men 45-49 years 5,761 5,427 -6%
Men 50-54 years 5,244 5,454 +4%
Men 55-59 years 4,485 4,809 +7%
Men 60-64 years 3,821 4,269 +12%
Men 65-69 years 3,093 3,507 +13%
Men 70-74 years 2,403 2,716 +13%
Men 75 years and over 1,564 1,846 +18%

Chart 2: A decade of diverging paths

Chart 1 compares only two years, so Chart 2 checks whether the split is a steady trend or a one-off. It groups people into eight age bands and follows each band every year from 2017 to 2026. In the default view, each line is indexed to its own 2017 level (2017 = 100), so a line above 100 means that band is now more likely to be victimised than it was in 2017, however high or low its rate started. Every band dipped during the COVID-19 lockdown years, when many types of crime fell. As restrictions lifted, the bands separated. The three oldest bands, shown in colour, were back above their 2017 levels by 2024 and kept climbing to a peak in 2025, while most younger bands, shown in grey, only recovered to around where they started. By 2026, the 75+ band sat at 123, the 65–74 band at 116 and the 55–64 band at 114, compared with 91 for 18–24 year olds. The “Actual rates” button keeps the comparison honest. In absolute terms, 18–24 year olds still had a rate of 4,723 per 100,000 in 2026, against 1,551 for people aged 75 and over. The story is not that older Victorians face the most crime, but that they are the only group whose risk is growing.

older_bands <- c("55–64", "65–74", "75+")
band_cols <- c("0–17" = "#C9C9C9", "18–24" = "#B5B5B5", "25–34" = "#A1A1A1",
               "35–44" = "#8D8D8D", "45–54" = "#797979",
               "55–64" = "#E69F00", "65–74" = "#D55E00", "75+" = "#8B2F00")

c2 <- pop_band |>
  filter(sex == "People") |>
  group_by(band) |>
  mutate(index = rate / rate[year == 2017] * 100) |>
  ungroup() |>
  mutate(tip = paste0("<b>Aged ", band, "</b> (", year, ")<br>Rate: ", fmt(rate),
                      " per 100,000<br>Index: ", fmt(index), " (2017 = 100)"))

views2 <- list(
  index = list(col = "index", label = "Change since 2017",
               ytitle = "Index (2017 = 100)",
               title = "<b>Since 2017, the three oldest age bands have pulled away from everyone else</b><br><sup>Victimisation rate indexed to 2017 = 100, by age band</sup>"),
  rate  = list(col = "rate", label = "Actual rates",
               ytitle = "Victim reports per 100,000 people",
               title = "<b>Older Victorians are still victimised less often, but the gap is closing</b><br><sup>Victim reports per 100,000 people, by age band</sup>"))

end_labels <- function(v) {
  d <- filter(c2, year == 2026, band %in% older_bands)
  lapply(seq_len(nrow(d)), function(i) {
    list(x = 2026, y = d[[v]][i], text = paste0("<b>", d$band[i], "</b>"), xanchor = "left",
         xshift = 6, showarrow = FALSE, font = list(color = band_cols[[as.character(d$band[i])]], size = 12))
  })
}
ref_line <- list(type = "line", xref = "paper", x0 = 0, x1 = 1, y0 = 100, y1 = 100,
                 line = list(color = "#444444", dash = "dot", width = 1))
src2 <- src_note("Crime Statistics Agency (2026), Victim Reports, Table 02. Rates for age bands derived (see Notes).")

p2 <- plot_ly(); grp2 <- character()
for (v in names(views2)) {
  for (b in band_levels) {
    d <- filter(c2, band == b)
    is_old <- b %in% older_bands
    p2 <- add_trace(p2, data = d, x = ~year, y = d[[views2[[v]]$col]],
                    type = "scatter", mode = "lines+markers", name = b, legendgroup = b,
                    showlegend = (v == "index"), visible = (v == "index"),
                    text = ~tip, hoverinfo = "text",
                    line = list(color = band_cols[[b]], width = ifelse(is_old, 3.5, 1.8)),
                    marker = list(color = band_cols[[b]], size = ifelse(is_old, 6, 4)))
    grp2 <- c(grp2, v)
  }
}

buttons2 <- lapply(names(views2), function(v) {
  list(method = "update", label = views2[[v]]$label,
       args = list(list(visible = grp2 == v, showlegend = grp2 == v),
                   list(title = list(text = views2[[v]]$title, x = 0, xanchor = "left", y = 0.97, yref = "container", yanchor = "top"),
                        `yaxis.title.text` = views2[[v]]$ytitle,
                        shapes = if (v == "index") list(ref_line) else list(),
                        annotations = c(end_labels(views2[[v]]$col), list(src2)))))
})

p2 |>
  layout(
    title = list(text = views2$index$title, x = 0, xanchor = "left", y = 0.97, yref = "container", yanchor = "top"), font = font_main,
    xaxis = list(title = "Year ending June", dtick = 1, range = c(2016.6, 2026.9)),
    yaxis = list(title = views2$index$ytitle),
    shapes = list(ref_line),
    annotations = c(end_labels("index"), list(src2)),
    updatemenus = list(list(type = "buttons", direction = "right", buttons = buttons2,
                            x = 0, xanchor = "left", y = 1.02, yanchor = "bottom",
                            bgcolor = "#F4F4F4", bordercolor = "#BBBBBB")),
    legend = list(title = list(text = "<b>Age band</b>")),
    hovermode = "closest",
    margin = list(t = 150, b = 100)
  ) |>
  tidy_config()

Chart description: a line chart from 2017 to 2026 with one line per age band. In the default “Change since 2017” view, every line starts at 100; the 55–64, 65–74 and 75+ lines (orange to dark red) finish well above 100, while the grey younger bands finish at or below it. The “Actual rates” button shows the underlying rates, where younger adults remain highest but the older bands are rising.

View underlying data
Victim reports per 100,000 people, all people, by age band and year (derived from Table 02)
Age band 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026
0–17 932 925 879 865 862 868 974 1,000 969 905
18–24 5,175 4,742 4,697 4,848 4,368 4,066 4,210 4,431 5,009 4,723
25–34 5,871 5,347 5,192 5,447 4,986 4,743 4,886 5,211 6,079 5,554
35–44 5,469 4,871 4,747 4,948 4,295 4,071 4,440 4,856 5,677 5,208
45–54 4,742 4,284 4,246 4,491 3,901 3,698 4,044 4,377 5,292 4,843
55–64 3,341 3,106 3,052 3,202 2,775 2,689 2,986 3,412 4,088 3,811
65–74 2,180 2,022 1,959 2,118 1,720 1,721 2,031 2,226 2,666 2,538
75+ 1,259 1,123 1,144 1,321 1,102 1,071 1,241 1,414 1,639 1,551

Chart 3: What is driving the rise?

Chart 3 asks what kinds of crime are behind the rise. Each bar shows how much the victimisation rate for one offence type changed between 2017 and 2026, after allowing for population growth: orange bars are increases and blue bars are decreases. The chart opens on Victorians aged 75 and over, and the menu lets you switch to any other age band for comparison. For the oldest group, deception (fraud, scams and similar offences) stands out, with its rate up 320%, more than four times its 2017 level. Stalking, harassment and threats rose 72%, assault 57% and theft 29%. These are offences that can happen over the phone, online or through people the victim knows, rather than on the street. Burglary is the one major offence that fell, but even here the oldest group benefited least: the 75+ burglary rate fell 17%, compared with a fall of 45% for people aged 25–34. Switching to younger bands shows a different picture, with smaller rises and much larger falls. Offence types with fewer than 50 reports in 2017 for a band are left out, because percentage changes on very small numbers can be misleading.

c3 <- offence_rates |>
  filter(sex == "People", year %in% c(2017, 2026)) |>
  select(band, offence, year, reports, rate) |>
  pivot_wider(names_from = year, values_from = c(reports, rate)) |>
  filter(reports_2017 >= 50) |>                # avoid misleading % changes on tiny bases
  mutate(change = (rate_2026 / rate_2017 - 1) * 100,
         tip = paste0("<b>", offence, "</b><br>Rate 2017: ", fmt(rate_2017, 1),
                      " → 2026: ", fmt(rate_2026, 1), " per 100,000",
                      "<br>Reports: ", fmt(reports_2017), " → ", fmt(reports_2026),
                      "<br>Change in rate: ", sgn(change), fmt(change), "%"))

offence_order <- c3 |> filter(band == "75+") |> arrange(change) |> pull(offence)
offence_order <- c(setdiff(unique(c3$offence), offence_order), offence_order)

c3_title <- function(b) list(
  text = paste0("<b>What changed for Victorians aged ", b, "?</b>",
                "<br><sup>% change in victimisation rate per 100,000, by offence type, 2017 to 2026</sup>"),
  x = 0, xanchor = "left", y = 0.97, yref = "container", yanchor = "top")

menu_bands <- c("75+", "65–74", "55–64", "45–54", "35–44", "25–34", "18–24", "0–17")
p3 <- plot_ly()
for (i in seq_along(menu_bands)) {
  d <- filter(c3, band == menu_bands[i])
  p3 <- add_bars(p3, data = d, x = ~change, y = ~offence, orientation = "h",
                 name = menu_bands[i], visible = (i == 1),
                 marker = list(color = ifelse(d$change >= 0, col_rise, col_fall)),
                 text = ~tip, hoverinfo = "text", textposition = "none")
}
buttons3 <- lapply(seq_along(menu_bands), function(i) {
  list(method = "update", label = paste("Aged", menu_bands[i]),
       args = list(list(visible = seq_along(menu_bands) == i),
                   list(title = c3_title(menu_bands[i]))))
})

p3 |>
  layout(
    title = c3_title("75+"), font = font_main, showlegend = FALSE,
    xaxis = list(title = "% change in rate, 2017 to 2026", ticksuffix = "%", zeroline = TRUE,
                 zerolinecolor = "#444444", zerolinewidth = 1.5),
    yaxis = list(title = "", categoryorder = "array", categoryarray = offence_order),
    annotations = list(src_note("Crime Statistics Agency (2026), Victim Reports, Tables 02 and 04. Rates derived (see Notes).")),
    updatemenus = list(list(buttons = buttons3, x = 0, xanchor = "left", y = 1.02,
                            yanchor = "bottom", bgcolor = "#F4F4F4", bordercolor = "#BBBBBB")),
    margin = list(t = 150, l = 10, b = 100)
  ) |>
  tidy_config()

Chart description: a horizontal bar chart of percentage change in victimisation rate for each offence type, with a menu to choose the age band. For the 75+ band, deception rises by several hundred per cent, and stalking, assault, theft and property damage all rise (orange bars), while burglary falls (blue bar). Choosing younger bands shows smaller rises and larger falls, especially for burglary.

View underlying data
Victim reports and rates per 100,000, by age band and offence type, 2017 and 2026 (Tables 02 and 04)
Age band Offence type Reports 2017 Reports 2026 Rate 2017 Rate 2026 Change in rate
75+ Deception (fraud, scams) 132 767 31.2 131.0 +320%
75+ Stalking, harassment & threats 68 162 16.1 27.7 +72%
75+ Assault 348 757 82.2 129.3 +57%
75+ Theft 2,336 4,181 551.6 714.3 +29%
75+ Arson & property damage 684 1,163 161.5 198.7 +23%
75+ Sexual offences 71 101 16.8 17.3 +3%
75+ Other crimes against the person 73 94 17.2 16.1 -7%
75+ Burglary / break and enter 1,620 1,853 382.6 316.6 -17%
65–74 Deception (fraud, scams) 191 906 35.9 139.7 +289%
65–74 Assault 889 1,792 167.1 276.3 +65%
65–74 Sexual offences 83 128 15.6 19.7 +27%
65–74 Theft 5,516 8,326 1,036.5 1,283.6 +24%
65–74 Arson & property damage 1,693 2,396 318.1 369.4 +16%
65–74 Stalking, harassment & threats 243 323 45.7 49.8 +9%
65–74 Other crimes against the person 146 142 27.4 21.9 -20%
65–74 Burglary / break and enter 2,837 2,445 533.1 376.9 -29%
55–64 Deception (fraud, scams) 336 1,370 47.7 174.9 +267%
55–64 Assault 2,499 4,094 354.5 522.8 +47%
55–64 Sexual offences 268 415 38.0 53.0 +39%
55–64 Stalking, harassment & threats 545 816 77.3 104.2 +35%
55–64 Theft 11,299 14,920 1,602.9 1,905.3 +19%
55–64 Arson & property damage 3,454 4,204 490.0 536.8 +10%
55–64 Other crimes against the person 308 373 43.7 47.6 +9%
55–64 Burglary / break and enter 4,834 3,633 685.8 463.9 -32%
45–54 Deception (fraud, scams) 503 1,762 62.1 205.4 +230%
45–54 Sexual offences 703 895 86.9 104.3 +20%
45–54 Assault 5,823 7,102 719.5 827.7 +15%
45–54 Stalking, harassment & threats 1,178 1,382 145.5 161.1 +11%
45–54 Theft 17,590 19,848 2,173.4 2,313.2 +6%
45–54 Arson & property damage 5,439 5,628 672.0 655.9 -2%
45–54 Other crimes against the person 645 635 79.7 74.0 -7%
45–54 Burglary / break and enter 6,496 4,273 802.6 498.0 -38%
35–44 Deception (fraud, scams) 671 2,321 79.1 217.5 +175%
35–44 Sexual offences 908 1,627 107.0 152.4 +43%
35–44 Assault 7,884 10,573 928.8 990.7 +7%
35–44 Stalking, harassment & threats 1,563 1,957 184.1 183.4 0%
35–44 Theft 21,110 26,289 2,487.1 2,463.3 -1%
35–44 Other crimes against the person 910 1,083 107.2 101.5 -5%
35–44 Arson & property damage 5,685 6,479 669.8 607.1 -9%
35–44 Burglary / break and enter 7,683 5,220 905.2 489.1 -46%
25–34 Deception (fraud, scams) 1,032 2,522 104.6 229.8 +120%
25–34 Sexual offences 1,189 2,702 120.5 246.2 +104%
25–34 Assault 10,650 12,192 1,079.0 1,110.8 +3%
25–34 Stalking, harassment & threats 1,819 2,027 184.3 184.7 +0%
25–34 Theft 28,488 29,804 2,886.3 2,715.5 -6%
25–34 Arson & property damage 5,722 5,704 579.7 519.7 -10%
25–34 Other crimes against the person 1,504 1,378 152.4 125.6 -18%
25–34 Burglary / break and enter 7,534 4,603 763.3 419.4 -45%
18–24 Deception (fraud, scams) 648 1,553 104.4 233.6 +124%
18–24 Sexual offences 1,293 2,435 208.3 366.3 +76%
18–24 Stalking, harassment & threats 989 1,063 159.3 159.9 +0%
18–24 Assault 7,000 6,907 1,127.4 1,039.0 -8%
18–24 Theft 15,116 14,532 2,434.6 2,185.9 -10%
18–24 Other crimes against the person 1,285 1,001 207.0 150.6 -27%
18–24 Arson & property damage 3,259 2,417 524.9 363.6 -31%
18–24 Burglary / break and enter 2,541 1,476 409.3 222.0 -46%
0–17 Deception (fraud, scams) 64 146 4.7 9.8 +110%
0–17 Other crimes against the person 823 1,250 59.8 83.8 +40%
0–17 Arson & property damage 179 215 13.0 14.4 +11%
0–17 Stalking, harassment & threats 462 515 33.6 34.5 +3%
0–17 Theft 1,666 1,854 121.1 124.3 +3%
0–17 Sexual offences 3,382 3,468 245.8 232.5 -5%
0–17 Assault 6,034 5,886 438.5 394.6 -10%
0–17 Burglary / break and enter 210 160 15.3 10.7 -30%

Chart 4: The scam surge

Because deception showed the biggest jump in Chart 3, Chart 4 looks at it in detail across every age band and every year. Each cell of the heatmap is one age band in one year. Brighter yellow means a higher value and darker purple a lower one, using a colour scale that stays readable for people with colour-vision deficiency. In the default “Growth since 2017” view, each cell shows the deception rate as a multiple of that band’s own 2017 rate, so the comparison is about how fast each group’s risk has grown. Deception has risen in every age group, but the growth gets steeper with age. For 25–34 year olds, the 2026 rate was 2.2 times the 2017 rate; for people aged 75 and over, it was 4.2 times. The “Actual rates” view shows the other half of the story. Working-age adults still report the most deception in absolute terms, with 230 victims per 100,000 people aged 25–34 in 2026, compared with 131 among those aged 75 and over. Older Victorians started from a much lower base, but they are catching up the fastest.

c4 <- offence_rates |>
  filter(sex == "People", offence == "Deception (fraud, scams)") |>
  group_by(band) |>
  mutate(mult = rate / rate[year == 2017]) |>
  ungroup() |>
  mutate(tip = paste0("<b>Aged ", band, ", ", year, "</b><br>", fmt(rate, 1),
                      " per 100,000 (", fmt(reports), " victim reports)<br>",
                      fmt(mult, 1), "× the 2017 rate"))

c4_titles <- list(
  mult = "<b>Deception has grown fastest among the oldest Victorians</b><br><sup>Deception victimisation rate as a multiple of each age band's 2017 rate</sup>",
  rate = "<b>In absolute terms, working-age adults still report the most deception</b><br><sup>Victims of deception offences per 100,000 people, by age band and year</sup>")

p4 <- plot_ly() |>
  add_trace(data = c4, x = ~year, y = ~band, z = ~mult, type = "heatmap",
            colorscale = "Viridis", text = ~tip, hoverinfo = "text", visible = TRUE,
            colorbar = list(title = list(text = "× 2017<br>rate"))) |>
  add_trace(data = c4, x = ~year, y = ~band, z = ~rate, type = "heatmap",
            colorscale = "Viridis", text = ~tip, hoverinfo = "text", visible = FALSE,
            colorbar = list(title = list(text = "Rate per<br>100,000")))

buttons4 <- list(
  list(method = "update", label = "Growth since 2017",
       args = list(list(visible = c(TRUE, FALSE)),
                   list(title = list(text = c4_titles$mult, x = 0, xanchor = "left", y = 0.97, yref = "container", yanchor = "top")))),
  list(method = "update", label = "Actual rates",
       args = list(list(visible = c(FALSE, TRUE)),
                   list(title = list(text = c4_titles$rate, x = 0, xanchor = "left", y = 0.97, yref = "container", yanchor = "top")))))

p4 |>
  layout(
    title = list(text = c4_titles$mult, x = 0, xanchor = "left", y = 0.97, yref = "container", yanchor = "top"), font = font_main,
    xaxis = list(title = "Year ending June", dtick = 1),
    yaxis = list(title = "Age band", categoryorder = "array", categoryarray = band_levels),
    annotations = list(src_note("Crime Statistics Agency (2026), Victim Reports, Tables 02 and 04. Rates derived (see Notes).")),
    updatemenus = list(list(type = "buttons", direction = "right", buttons = buttons4,
                            x = 0, xanchor = "left", y = 1.02, yanchor = "bottom",
                            bgcolor = "#F4F4F4", bordercolor = "#BBBBBB")),
    margin = list(t = 150, b = 100)
  ) |>
  tidy_config()

Chart description: a heatmap with years across and age bands down, using a colour-blind-safe purple-to-yellow scale. In the default “Growth since 2017” view, the oldest bands in the bottom rows turn the brightest yellow by 2026, showing the largest growth. The “Actual rates” view shows working-age bands with the highest absolute rates.

View underlying data
Deception victim reports per 100,000 people, by age band and year (Tables 02 and 04)
Age band 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026
0–17 4.7 6.6 6.2 7.8 9.3 7.4 9.6 10.1 10.6 9.8
18–24 104.4 175.2 190.6 235.8 239.0 178.5 205.4 205.4 201.8 233.6
25–34 104.6 178.1 209.2 242.7 253.5 197.9 229.1 228.1 216.2 229.8
35–44 79.1 130.5 169.6 189.3 197.3 173.8 205.0 195.7 189.0 217.5
45–54 62.1 102.2 123.0 154.1 164.9 144.2 184.7 183.1 187.4 205.4
55–64 47.7 76.1 104.4 115.0 126.8 111.0 155.6 146.4 152.4 174.9
65–74 35.9 53.3 80.6 79.7 93.7 83.4 139.7 124.3 133.3 139.7
75+ 31.2 35.0 60.0 62.7 80.4 69.1 103.1 101.9 99.4 131.0

Chart 5: Older women are carrying more of the rise

The final chart asks who within the older population is most affected, by comparing women and men directly. Each row is an age band. The orange circle shows the percentage change in the victimisation rate for women between 2017 and 2026, the blue diamond shows the same for men, and the grey line between them shows the size of the gap. Points to the right of the zero line mean the rate rose. Across all offences, both sexes follow the turning point seen in Chart 1, but from age 45 onwards the increase is larger for women in every band. Among Victorians aged 75 and over, the rate rose 29% for women compared with 18% for men. The menu breaks this down by offence type, and two offences stand out. Deception among women aged 75 and over rose 390%, compared with 257% for men of the same age. For sexual offences, the rate for women aged 55–64 rose 82%, while for men of the same age it fell 24%. Groups with fewer than 30 reports in 2017 are not shown, because changes based on very small numbers are unreliable.

# All offences (Table 02 rates) plus each offence type (Table 04 derived rates), by sex
c5_all <- bind_rows(
  pop_band |> mutate(option = "All offences"),
  offence_rates |> rename(option = offence)
) |>
  filter(sex %in% c("Females", "Males"), year %in% c(2017, 2026)) |>
  select(option, sex, band, year, reports, rate) |>
  pivot_wider(names_from = year, values_from = c(reports, rate)) |>
  mutate(change = ifelse(reports_2017 >= 30, (rate_2026 / rate_2017 - 1) * 100, NA),
         who = ifelse(sex == "Females", "Women", "Men"),
         tip = paste0("<b>", who, ", aged ", band, "</b><br>", option,
                      "<br>Rate 2017: ", fmt(rate_2017, 1), " → 2026: ", fmt(rate_2026, 1),
                      " per 100,000<br>Change: ", sgn(change), fmt(change), "%"))

options5 <- c("All offences", "Deception (fraud, scams)", "Assault", "Sexual offences",
              "Stalking, harassment & threats", "Theft", "Arson & property damage",
              "Burglary / break and enter")
c5_title <- function(o) {
  headline <- if (o == "All offences") {
    "<b>From 45 onwards, women's victimisation rates are rising faster than men's</b>"
  } else {
    paste0("<b>Women vs men: change in victimisation rate for ", tolower(o), "</b>")
  }
  list(text = paste0(headline, "<br><sup>% change in rate per 100,000, 2017 to 2026, by sex and age band",
                     if (o == "All offences") ", all offences" else "", "</sup>"),
       x = 0, xanchor = "left", y = 0.97, yref = "container", yanchor = "top")
}

p5 <- plot_ly(); grp5 <- character()
for (o in options5) {
  d  <- filter(c5_all, option == o)
  dw <- d |> select(band, who, change) |> pivot_wider(names_from = who, values_from = change) |>
    filter(!is.na(Women), !is.na(Men))
  vis <- (o == "All offences")
  if (nrow(dw) > 0) {
    p5 <- add_segments(p5, data = dw, x = ~Women, xend = ~Men, y = ~band, yend = ~band,
                       line = list(color = "#CCCCCC", width = 3), showlegend = FALSE,
                       hoverinfo = "none", visible = vis)
    grp5 <- c(grp5, o)
  }
  dF <- filter(d, sex == "Females", !is.na(change))
  dM <- filter(d, sex == "Males", !is.na(change))
  if (nrow(dF) > 0) {
    p5 <- add_markers(p5, data = dF, x = ~change, y = ~band,
                      name = "Women", legendgroup = "Women", visible = vis,
                      marker = list(color = col_women, size = 12, symbol = "circle"),
                      text = ~tip, hoverinfo = "text")
    grp5 <- c(grp5, o)
  }
  if (nrow(dM) > 0) {
    p5 <- add_markers(p5, data = dM, x = ~change, y = ~band,
                      name = "Men", legendgroup = "Men", visible = vis,
                      marker = list(color = col_men, size = 12, symbol = "diamond"),
                      text = ~tip, hoverinfo = "text")
    grp5 <- c(grp5, o)
  }
}

buttons5 <- lapply(options5, function(o) {
  list(method = "update", label = o,
       args = list(list(visible = grp5 == o),
                   list(title = c5_title(o), `xaxis.autorange` = TRUE)))
})

p5 |>
  layout(
    title = c5_title("All offences"), font = font_main,
    xaxis = list(title = "% change in rate, 2017 to 2026", ticksuffix = "%",
                 zeroline = TRUE, zerolinecolor = "#444444", zerolinewidth = 1.5),
    yaxis = list(title = "Age band", categoryorder = "array", categoryarray = band_levels),
    annotations = list(src_note("Crime Statistics Agency (2026), Victim Reports, Tables 02 and 04. Groups with fewer than 30 reports in 2017 are not shown.")),
    updatemenus = list(list(buttons = buttons5, x = 0, xanchor = "left", y = 1.02,
                            yanchor = "bottom", bgcolor = "#F4F4F4", bordercolor = "#BBBBBB")),
    legend = list(orientation = "h", x = 1, xanchor = "right", y = 1.02, yanchor = "bottom"),
    margin = list(t = 150, b = 110)
  ) |>
  tidy_config()

Chart description: a dot plot with one row per age band and two markers per row, an orange circle for women and a blue diamond for men, showing the percentage change in victimisation rate. A menu switches between all offences and individual offence types. For all offences, most markers under 45 sit left of zero (decreases); from 45 upwards both sit right of zero, with the women’s circle further right. Groups with fewer than 30 reports in 2017 are not shown.

View underlying data
% change in victimisation rate per 100,000, 2017 to 2026, by offence type, sex and age band (Tables 02 and 04)
Offence type Age band Women: change Men: change
All offences 0–17 -9% +4%
All offences 18–24 -11% -7%
All offences 25–34 -1% -9%
All offences 35–44 -5% -5%
All offences 45–54 +7% -1%
All offences 55–64 +23% +9%
All offences 65–74 +25% +13%
All offences 75+ +29% +18%
Deception (fraud, scams) 0–17 +42% +183%
Deception (fraud, scams) 18–24 +108% +137%
Deception (fraud, scams) 25–34 +123% +117%
Deception (fraud, scams) 35–44 +171% +180%
Deception (fraud, scams) 45–54 +259% +209%
Deception (fraud, scams) 55–64 +266% +266%
Deception (fraud, scams) 65–74 +295% +286%
Deception (fraud, scams) 75+ +390% +257%
Assault 0–17 -11% -9%
Assault 18–24 -7% -9%
Assault 25–34 +9% -4%
Assault 35–44 +13% -1%
Assault 45–54 +22% +8%
Assault 55–64 +58% +40%
Assault 65–74 +77% +59%
Assault 75+ +53% +63%
Sexual offences 0–17 -6% -3%
Sexual offences 18–24 +62% +186%
Sexual offences 25–34 +95% +182%
Sexual offences 35–44 +46% +20%
Sexual offences 45–54 +39% -27%
Sexual offences 55–64 +82% -24%
Sexual offences 65–74 +64% -16%
Sexual offences 75+ +17% n/a (small numbers)
Stalking, harassment & threats 0–17 -14% +37%
Stalking, harassment & threats 18–24 -3% +10%
Stalking, harassment & threats 25–34 +1% -2%
Stalking, harassment & threats 35–44 +1% -3%
Stalking, harassment & threats 45–54 +11% +11%
Stalking, harassment & threats 55–64 +43% +27%
Stalking, harassment & threats 65–74 +13% +7%
Stalking, harassment & threats 75+ +72% +71%
Theft 0–17 -16% +12%
Theft 18–24 -16% -7%
Theft 25–34 -3% -8%
Theft 35–44 -3% +0%
Theft 45–54 +14% +2%
Theft 55–64 +34% +12%
Theft 65–74 +34% +21%
Theft 75+ +36% +24%
Arson & property damage 0–17 -15% +43%
Arson & property damage 18–24 -36% -24%
Arson & property damage 25–34 -13% -8%
Arson & property damage 35–44 -13% -6%
Arson & property damage 45–54 -2% -2%
Arson & property damage 55–64 +10% +10%
Arson & property damage 65–74 +23% +12%
Arson & property damage 75+ +36% +13%
Burglary / break and enter 0–17 -38% -23%
Burglary / break and enter 18–24 -51% -40%
Burglary / break and enter 25–34 -44% -46%
Burglary / break and enter 35–44 -52% -41%
Burglary / break and enter 45–54 -41% -36%
Burglary / break and enter 55–64 -31% -32%
Burglary / break and enter 65–74 -25% -31%
Burglary / break and enter 75+ -13% -21%

Why this matters

Victoria is ageing, and its oldest residents are the one group for whom the crime picture is getting worse rather than better. The offences behind that rise, especially fraud and scams, assault, and stalking and harassment, can be less visible than street crime. They can happen over the phone, online, or at the hands of someone the victim knows. With Victorians heading to a state election in November 2026, the data suggests a question worth asking of every party: what is the plan for keeping older Victorians safe?

Notes on the data

  • Data source. All five charts use one high-quality, official source: the Crime Statistics Agency’s Victim Reports data tables for the year ending June 2026, covering July 2016 to June 2026 (Crime Statistics Agency, 2026). Table 02 gives counts and rates by sex and age; Table 04 gives counts by sex, age and offence type.
  • These are reports to police, not all crime. A rise can reflect more crime, more reporting, or both. Growing awareness of scams and elder abuse may lead more older people, or their families, to report.
  • “Victim reports” count reports, not unique people. One person can be counted more than once in a year if they are victimised more than once.
  • Rates for Charts 2 to 5 are derived. The source publishes rates by 5-year age group (Table 02) but only counts by offence type (Table 04). Population for each group was back-calculated from Table 02 (population = reports ÷ rate × 100,000) and summed into the wider age bands used in Table 04. Rates per 100,000 were then recalculated, which removes the effect of Victoria’s growing older population.
  • Small numbers are suppressed. Offence types with fewer than 50 reports in 2017 (Chart 3), and sex and age groups with fewer than 30 reports in 2017 (Chart 5), are not shown, because percentage changes on very small numbers are misleading.
  • Exclusions. Victim reports for organisations, and records with unknown age or sex, are excluded.
  • Design. Colours follow the Okabe and Ito (2008) colour-blind-safe palette, and Chart 4 uses the perceptually uniform Viridis scale. Women and men are distinguished by marker shape as well as colour. Interactive charts were built with plotly for R (Sievert, 2020).

References

Anthropic. (2026). Claude (Opus 5.5 version) [Large language model]. https://claude.ai

Crime Statistics Agency. (2026). Victim reports: Data tables, year ending June 2026 [Data set]. Victorian Government. https://files.crimestatistics.vic.gov.au/2026-09/Data_Tables_Victim_Reports_Visualisation_Year_Ending_June_2026.xlsx

Okabe, M., & Ito, K. (2008). Color universal design (CUD): How to make figures and presentations that are friendly to colorblind people. J*Fly. https://jfly.uni-koeln.de/color/

R Core Team. (2026). R: A language and environment for statistical computing [Computer software]. R Foundation for Statistical Computing. https://www.R-project.org/

Sievert, C. (2020). Interactive web-based data visualization with R, plotly, and shiny. Chapman and Hall/CRC. https://plotly-r.com

Wickham, H., Averick, M., Bryan, J., Chang, W., McGowan, L. D., François, R., Grolemund, G., Hayes, A., Henry, L., Hester, J., Kuhn, M., Pedersen, T. L., Miller, E., Bache, S. M., Müller, K., Ooms, J., Robinson, D., Seidel, D. P., Spinu, V., … Yutani, H. (2019). Welcome to the tidyverse. Journal of Open Source Software, 4(43), 1686. https://doi.org/10.21105/joss.01686

Acknowledgements

Data for this piece came from the Crime Statistics Agency’s Victim Reports data tables for the year ending June 2026, published on the Victorian Government’s DataVic portal under a Creative Commons Attribution 4.0 International (CC BY 4.0) licence. The report was written and rendered in R Markdown using the readxl, dplyr, tidyr, plotly and knitr packages, published on RPubs, and submitted via Cadmus.

I used Claude (Anthropic, 2026) to help explore the data, draft and debug the R code for the charts, suggest wording for the narrative, and check the report against the marking rubric. I reviewed, ran and checked all code and figures against the source data, and edited the text in my own words.