pkgs <- c("tidyverse","janitor","lubridate","scales")
to_install <- pkgs[!pkgs %in% installed.packages()[,1]]
if(length(to_install)) install.packages(to_install, quiet=TRUE)
invisible(lapply(pkgs, library, character.only = TRUE))
Cycling plays a major role in Melbourne’s transport network, especially for short daily trips. The Super Tuesday bike count dataset provides a detailed snapshot of when, where and how people ride across the city. By transforming and visualising open data, this report uncovers meaningful patterns: Which locations are busiest, which sites show strong female participation, and where cycling infrastructure may need improvement. Using R, the dataset was cleaned, analysed and presented as clear visual insights rather than raw numbers. These findings help city planners and councils understand cycling behaviour, identify gaps and support safer, more inclusive cycling routes for commuters and recreational riders.
bike_counts <- readr::read_csv("C:/Users/vishal reddy/Downloads/annual-bike-counts-super-tuesday.csv") |>
janitor::clean_names()
## Rows: 352 Columns: 82
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (5): state, electorate, description, location, geolocation
## dbl (62): site_id, latitude, longitude, legs, layout_1, layout_1_enter, layo...
## lgl (15): layout_6, layout_6_enter, leg1-6, leg2-6, leg3-6, leg4-6, leg5-6, ...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
bike <- bike_counts
names(bike)
## [1] "state" "electorate" "site_id" "latitude"
## [5] "longitude" "legs" "description" "layout_1"
## [9] "layout_1_enter" "layout_2" "layout_2_enter" "layout_3"
## [13] "layout_3_enter" "layout_4" "layout_4_enter" "layout_5"
## [17] "layout_5_enter" "layout_6" "layout_6_enter" "leg1_2"
## [21] "leg1_3" "leg1_4" "leg1_5" "leg1_6"
## [25] "leg2_1" "leg2_3" "leg2_4" "leg2_5"
## [29] "leg2_6" "leg3_1" "leg3_2" "leg3_4"
## [33] "leg3_5" "leg3_6" "leg4_1" "leg4_2"
## [37] "leg4_3" "leg4_5" "leg4_6" "leg5_1"
## [41] "leg5_2" "leg5_3" "leg5_4" "leg5_6"
## [45] "leg6_1" "leg6_2" "leg6_3" "leg6_4"
## [49] "leg6_5" "leg1_enter" "leg1_exit" "leg1_total"
## [53] "leg2_enter" "leg2_exit" "leg2_total" "leg3_enter"
## [57] "leg3_exit" "leg3_total" "leg4_enter" "leg4_exit"
## [61] "leg4_total" "leg5_enter" "leg5_exit" "leg5_total"
## [65] "leg6_enter" "leg6_exit" "leg6_total" "female"
## [69] "male" "not_known" "total" "year"
## [73] "x7_00_am" "x7_15_am" "x7_30_am" "x7_45_am"
## [77] "x8_00_am" "x8_15_am" "x8_30_am" "x8_45_am"
## [81] "location" "geolocation"
dplyr::glimpse(bike)
## Rows: 352
## Columns: 82
## $ state <chr> "VIC", "VIC", "VIC", "VIC", "VIC", "VIC", "VIC", "VIC",…
## $ electorate <chr> "Melbourne", "Melbourne", "Melbourne", "Melbourne", "Me…
## $ site_id <dbl> 4427, 4433, 4450, 4399, 4411, 4416, 4420, 4448, 4984, 4…
## $ latitude <dbl> -37.81175, -37.81509, -37.82521, -37.78798, -37.79663, …
## $ longitude <dbl> 144.9565, 144.9447, 144.9570, 144.9590, 144.9512, 144.9…
## $ legs <dbl> 4, 3, 5, 2, 4, 4, 4, 3, 4, 3, 4, 4, 3, 4, 4, 2, 4, 4, 4…
## $ description <chr> "La Trobe towards Exhibition St [E], William St [S], La…
## $ layout_1 <dbl> 70, 70, 50, 5, 45, 6, 8, 100, 7, 8, 70, 7, 160, 70, 70,…
## $ layout_1_enter <dbl> 250, 250, 230, 185, 225, 186, 188, 280, 187, 188, 250, …
## $ layout_2 <dbl> 160, 161, 160, 186, 135, 70, 98, 190, 98, 188, 160, 98,…
## $ layout_2_enter <dbl> 340, 341, 340, 6, 315, 250, 278, 10, 278, 8, 340, 278, …
## $ layout_3 <dbl> 250, 341, 213, NA, 225, 160, 188, 345, 189, 278, 250, 1…
## $ layout_3_enter <dbl> 70, 161, 33, NA, 45, 340, 8, 165, 9, 98, 70, 360, 160, …
## $ layout_4 <dbl> 340, NA, 236, NA, 315, 250, 278, NA, 278, NA, 340, 278,…
## $ layout_4_enter <dbl> 160, NA, 56, NA, 135, 70, 98, NA, 98, NA, 160, 98, NA, …
## $ layout_5 <dbl> NA, NA, 340, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ layout_5_enter <dbl> NA, NA, 160, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ layout_6 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ layout_6_enter <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg1_2 <dbl> 27, 55, 0, 947, 3, 2, 3, 29, 0, 13, 18, 5, 8, 17, 6, 98…
## $ leg1_3 <dbl> 89, 17, NA, NA, 27, 360, 346, 160, 0, 2, 286, 569, 46, …
## $ leg1_4 <dbl> 0, NA, 12, NA, 3, 112, 66, NA, 1, NA, 8, 4, NA, 4, 16, …
## $ leg1_5 <dbl> NA, NA, 8, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ leg1_6 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg2_1 <dbl> 8, 31, 2, 30, 9, 0, 29, 18, 0, 11, 3, 3, 8, 17, 10, 68,…
## $ leg2_3 <dbl> 13, 96, NA, NA, 1, 9, 87, 19, 5, 1, 4, 3, 12, 12, 0, NA…
## $ leg2_4 <dbl> 19, NA, 3, NA, 29, 103, 200, NA, 25, NA, 21, 12, NA, 94…
## $ leg2_5 <dbl> NA, NA, 230, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ leg2_6 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg3_1 <dbl> 120, 191, NA, NA, 17, 17, 25, 194, 0, 0, 67, 49, 148, 1…
## $ leg3_2 <dbl> 31, 669, NA, NA, 13, 2, 8, 94, 9, 4, 32, 1, 79, 23, 1, …
## $ leg3_4 <dbl> 6, NA, NA, NA, 0, 4, 0, NA, 0, NA, 1, 3, NA, 3, 1, NA, …
## $ leg3_5 <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg3_6 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg4_1 <dbl> 17, NA, 11, NA, 17, 5, 3, NA, 0, NA, 3, 8, NA, 1, 3, NA…
## $ leg4_2 <dbl> 240, NA, 2, NA, 249, 17, 35, NA, 88, NA, 67, 165, NA, 4…
## $ leg4_3 <dbl> 33, NA, NA, NA, 7, 19, 9, NA, 5, NA, 29, 66, NA, 6, 0, …
## $ leg4_5 <dbl> NA, NA, 318, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ leg4_6 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg5_1 <dbl> NA, NA, 19, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg5_2 <dbl> NA, NA, 78, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg5_3 <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg5_4 <dbl> NA, NA, 79, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg5_6 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg6_1 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg6_2 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg6_3 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg6_4 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg6_5 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg1_enter <dbl> 116, 72, 20, 947, 33, 474, 415, 189, 1, 15, 312, 578, 5…
## $ leg1_exit <dbl> 145, 222, 32, 30, 43, 22, 57, 212, 0, 11, 73, 60, 156, …
## $ leg1_total <dbl> 261, 294, 52, 977, 76, 496, 472, 401, 1, 26, 385, 638, …
## $ leg2_enter <dbl> 40, 127, 235, 30, 39, 112, 316, 37, 30, 12, 28, 18, 20,…
## $ leg2_exit <dbl> 298, 724, 80, 947, 265, 21, 46, 123, 97, 17, 117, 171, …
## $ leg2_total <dbl> 338, 851, 315, 977, 304, 133, 362, 160, 127, 29, 145, 1…
## $ leg3_enter <dbl> 157, 860, NA, NA, 30, 23, 33, 288, 9, 4, 100, 53, 227, …
## $ leg3_exit <dbl> 135, 113, NA, NA, 35, 388, 442, 179, 10, 3, 319, 638, 5…
## $ leg3_total <dbl> 292, 973, NA, NA, 65, 411, 475, 467, 19, 7, 419, 691, 2…
## $ leg4_enter <dbl> 290, NA, 331, NA, 273, 41, 47, NA, 93, NA, 99, 239, NA,…
## $ leg4_exit <dbl> 25, NA, 94, NA, 32, 219, 266, NA, 26, NA, 30, 19, NA, 1…
## $ leg4_total <dbl> 315, NA, 425, NA, 305, 260, 313, NA, 119, NA, 129, 258,…
## $ leg5_enter <dbl> NA, NA, 176, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ leg5_exit <dbl> NA, NA, 556, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ leg5_total <dbl> NA, NA, 732, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ leg6_enter <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg6_exit <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ leg6_total <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ female <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 173, 0, 0, …
## $ male <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 660, 0, 0, …
## $ not_known <dbl> 603, 1059, 762, 977, 375, 650, 811, 514, 133, 31, 539, …
## $ total <dbl> 603, 1059, 762, 977, 375, 650, 811, 514, 133, 31, 539, …
## $ year <dbl> 2010, 2010, 2010, 2011, 2011, 2011, 2011, 2011, 2011, 2…
## $ x7_00_am <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ x7_15_am <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ x7_30_am <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ x7_45_am <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ x8_00_am <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ x8_15_am <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ x8_30_am <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ x8_45_am <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ location <chr> "POINT (144.956451 -37.811749000000006)", "POINT (144.9…
## $ geolocation <chr> "-37.811749, 144.956451", "-37.815089, 144.944713", "-3…
dplyr::slice_head(bike, n = 5)
## # A tibble: 5 × 82
## state electorate site_id latitude longitude legs description layout_1
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <dbl>
## 1 VIC Melbourne 4427 -37.8 145. 4 La Trobe towards E… 70
## 2 VIC Melbourne 4433 -37.8 145. 3 La Trobe [E], Capi… 70
## 3 VIC Melbourne 4450 -37.8 145. 5 Whiteman St [NE], … 50
## 4 VIC Melbourne 4399 -37.8 145. 2 Royal Pde/shared p… 5
## 5 VIC Melbourne 4411 -37.8 145. 4 Gatehouse St [NE],… 45
## # ℹ 74 more variables: layout_1_enter <dbl>, layout_2 <dbl>,
## # layout_2_enter <dbl>, layout_3 <dbl>, layout_3_enter <dbl>, layout_4 <dbl>,
## # layout_4_enter <dbl>, layout_5 <dbl>, layout_5_enter <dbl>, layout_6 <lgl>,
## # layout_6_enter <lgl>, leg1_2 <dbl>, leg1_3 <dbl>, leg1_4 <dbl>,
## # leg1_5 <dbl>, leg1_6 <lgl>, leg2_1 <dbl>, leg2_3 <dbl>, leg2_4 <dbl>,
## # leg2_5 <dbl>, leg2_6 <lgl>, leg3_1 <dbl>, leg3_2 <dbl>, leg3_4 <dbl>,
## # leg3_5 <dbl>, leg3_6 <lgl>, leg4_1 <dbl>, leg4_2 <dbl>, leg4_3 <dbl>, …
# number of rows and columns
dim(bike)
## [1] 352 82
# preview the first few rows
dplyr::slice_head(bike, n = 5)
## # A tibble: 5 × 82
## state electorate site_id latitude longitude legs description layout_1
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <dbl>
## 1 VIC Melbourne 4427 -37.8 145. 4 La Trobe towards E… 70
## 2 VIC Melbourne 4433 -37.8 145. 3 La Trobe [E], Capi… 70
## 3 VIC Melbourne 4450 -37.8 145. 5 Whiteman St [NE], … 50
## 4 VIC Melbourne 4399 -37.8 145. 2 Royal Pde/shared p… 5
## 5 VIC Melbourne 4411 -37.8 145. 4 Gatehouse St [NE],… 45
## # ℹ 74 more variables: layout_1_enter <dbl>, layout_2 <dbl>,
## # layout_2_enter <dbl>, layout_3 <dbl>, layout_3_enter <dbl>, layout_4 <dbl>,
## # layout_4_enter <dbl>, layout_5 <dbl>, layout_5_enter <dbl>, layout_6 <lgl>,
## # layout_6_enter <lgl>, leg1_2 <dbl>, leg1_3 <dbl>, leg1_4 <dbl>,
## # leg1_5 <dbl>, leg1_6 <lgl>, leg2_1 <dbl>, leg2_3 <dbl>, leg2_4 <dbl>,
## # leg2_5 <dbl>, leg2_6 <lgl>, leg3_1 <dbl>, leg3_2 <dbl>, leg3_4 <dbl>,
## # leg3_5 <dbl>, leg3_6 <lgl>, leg4_1 <dbl>, leg4_2 <dbl>, leg4_3 <dbl>, …
# summary of key numeric column
summary(bike$count)
## Warning: Unknown or uninitialised column: `count`.
## Length Class Mode
## 0 NULL NULL
# check missing values
colSums(is.na(bike))
## state electorate site_id latitude longitude
## 0 0 0 0 0
## legs description layout_1 layout_1_enter layout_2
## 0 1 0 0 0
## layout_2_enter layout_3 layout_3_enter layout_4 layout_4_enter
## 1 24 24 79 79
## layout_5 layout_5_enter layout_6 layout_6_enter leg1_2
## 328 328 352 352 51
## leg1_3 leg1_4 leg1_5 leg1_6 leg2_1
## 72 115 326 352 51
## leg2_3 leg2_4 leg2_5 leg2_6 leg3_1
## 77 120 331 352 72
## leg3_2 leg3_4 leg3_5 leg3_6 leg4_1
## 77 120 331 352 115
## leg4_2 leg4_3 leg4_5 leg4_6 leg5_1
## 120 120 326 352 326
## leg5_2 leg5_3 leg5_4 leg5_6 leg6_1
## 331 331 326 352 352
## leg6_2 leg6_3 leg6_4 leg6_5 leg1_enter
## 352 352 352 352 46
## leg1_exit leg1_total leg2_enter leg2_exit leg2_total
## 46 46 51 51 51
## leg3_enter leg3_exit leg3_total leg4_enter leg4_exit
## 72 72 72 115 115
## leg4_total leg5_enter leg5_exit leg5_total leg6_enter
## 115 326 326 326 352
## leg6_exit leg6_total female male not_known
## 352 352 172 172 0
## total year x7_00_am x7_15_am x7_30_am
## 0 0 214 214 214
## x7_45_am x8_00_am x8_15_am x8_30_am x8_45_am
## 214 214 214 214 214
## location geolocation
## 0 0
library(dplyr)
library(ggplot2)
# find numeric bike count column
bike_numeric <- bike |> select(where(is.numeric))
# remove latitude/longitude from sums
bike_numeric <- bike_numeric |> select(-latitude, -longitude)
# add totals by location
top_locations <- bike |>
group_by(description) |>
summarise(total_riders = sum(bike_numeric[[1]], na.rm = TRUE)) |>
arrange(desc(total_riders)) |>
slice_head(n = 10)
ggplot(top_locations, aes(x = reorder(description, total_riders), y = total_riders)) +
geom_col(fill = "steelblue") +
coord_flip() +
labs(
title = "Top 10 Busiest Bike Locations in Melbourne",
x = "Location",
y = "Total Riders"
)
The Top 10 busiest bike locations show that most riders travel through central, high-traffic areas of Melbourne. Locations such as Collins Street, Capital City Trail, and Harbour Esplanade record the highest counts, indicating that cycling is heavily used for daily commuting rather than recreation alone. These sites connect train stations, business districts, universities, and waterfront paths, which explains the consistently high volume of cyclists. The results suggest that well-maintained cycling corridors close to public transport and workplaces are critical for supporting active travel in Melbourne.
library(dplyr)
library(ggplot2)
gender_totals <- bike |>
summarise(
male_total = sum(male, na.rm = TRUE),
female_total = sum(female, na.rm = TRUE)
) |>
tidyr::pivot_longer(cols = everything(), names_to = "gender", values_to = "count")
ggplot(gender_totals, aes(x = gender, y = count, fill = gender)) +
geom_col() +
labs(
title = "Total Cyclists by Gender",
x = "Gender",
y = "Number of Riders"
) +
scale_fill_manual(values = c("steelblue", "pink")) +
theme_minimal()
The gender analysis shows that male riders significantly outnumber
female riders. This pattern is consistent with typical metropolitan
cycling behaviour, where males are more likely to commute by bike.
However, the presence of thousands of female cyclists indicates that
bike infrastructure is being used by a wide demographic. Increasing
safe, protected lanes and improving lighting and signage could encourage
even more women to cycle regularly, reducing the gender gap in active
transport.
library(dplyr)
library(ggplot2)
female_locs <- bike |>
group_by(description) |>
summarise(female_total = sum(female, na.rm = TRUE)) |>
arrange(desc(female_total)) |>
slice_head(n = 10)
ggplot(female_locs, aes(x = reorder(description, female_total), y = female_total)) +
geom_col(fill = "purple") +
coord_flip() +
labs(
title = "Top 10 Locations with Highest Female Cyclists",
x = "Location",
y = "Total Female Riders"
) +
theme_minimal()
The locations above represent the highest female cyclist participation
in Melbourne. Most of these are located on protected bike paths,
riverside trails, or low-traffic corridors. This pattern suggests that
women are more likely to ride in environments that feel safer and
physically separated from main roads. For city planners, this insight
highlights the value of protected lanes, better lighting, and calmer
road designs to encourage more female ridership across the network.
Investing in safer cycling infrastructure could increase overall participation and help reduce gender gaps in cycling activity.
## Percentage of Female Participation at Top Locations (safe)
library(dplyr)
library(ggplot2)
# auto-detect gender columns (case-insensitive)
female_cols <- grep("female", names(bike), ignore.case = TRUE, value = TRUE)
male_cols <- grep("male", names(bike), ignore.case = TRUE, value = TRUE)
if (length(female_cols) > 0 && length(male_cols) > 0) {
female_share <- bike %>%
mutate(
female = rowSums(across(all_of(female_cols)), na.rm = TRUE),
male = rowSums(across(all_of(male_cols)), na.rm = TRUE),
total = female + male
) %>%
filter(total > 0) %>% # keep valid rows
group_by(description) %>%
summarise(
female_percent = round(100 * sum(female) / sum(total), 1),
.groups = "drop"
) %>%
arrange(desc(female_percent)) %>%
slice_head(n = 10)
if (nrow(female_share) > 0) {
ggplot(female_share, aes(x = reorder(description, female_percent),
y = female_percent)) +
geom_col() +
coord_flip() +
labs(title = "Top 10 Locations by Percentage of Female Cyclists",
x = "Location", y = "Female % of Total Riders") +
theme_minimal()
} else {
cat("**Note:** Gender columns exist but resulted in no valid rows (all zero/NA totals). Plot skipped.")
}
} else {
cat("**Note:** This dataset does not include separate male/female columns, ",
"so a percentage-by-gender plot cannot be computed. ")
}
Female participation is highest at shared paths and protected off-road
corridors, not on busy main roads.This suggests many women prefer
low-stress environments with physical separation from traffic.Locations
with lighting, continuous lanes and safer intersections show noticeably
higher female share.Planners can use this insight to prioritise
protected bike lanes and safer junction treatments.Improving comfort and
safety can help close the gender gap in cycling participation.Stronger
female ridership is a marker of an inclusive and well-connected cycling
network.
library(dplyr)
library(ggplot2)
least_busy <- bike |>
mutate(
total_calc = if ("total" %in% names(bike)) {
total
} else {
rowSums(dplyr::select(bike, tidyselect::contains("total")), na.rm = TRUE)
}
) |>
group_by(description) |>
summarise(total = sum(total_calc, na.rm = TRUE), .groups = "drop") |>
arrange(total) |>
slice_head(n = 10)
ggplot(least_busy, aes(x = reorder(description, total), y = total)) +
geom_col(fill = "steelblue") +
coord_flip() +
labs(
title = "10 Least Busy Cycling Locations",
x = "Location",
y = "Total Riders"
) +
theme_minimal()
These sites record the lowest cyclist counts. They’re good “opportunity locations” for targeted improvements (protected lanes, wayfinding, lighting) to lift usage and connect nearby high-demand corridors.
The analysis shows that Melbourne’s busiest cycling locations are concentrated along protected paths and major commuting corridors. Female participation is highest where riders feel safe, separated from traffic and supported by good lighting and wayfinding. Meanwhile, low-usage locations highlight opportunity sites for better infrastructure. Together, these insights support evidence-based planning: adding protected lanes, improving junction safety, and strengthening connections to job and education hubs. In short, open data reveals clear actions to make cycling safer, more inclusive and a stronger part of Melbourne’s transport future.