I recently moved to St Kilda. I’ve noticed a lot of the speed limits around me being changed. More and more streets are now 40 km/h. Chapel St has now changed from 40km/h to 30 km/h as well! It got me wondering why. Was it about keeping people on foot safe, or was something else going on? And is it actually working?
St Kilda is part of the City of Port Phillip. Between 2017 and 2019 Port Phillip moved a big part of its local streets into 40 km/h zones. That gave me a real test. If lower limits make streets safer then Port Phillip’s crashes should have dropped more than in similar councils that kept their old limits. Fewer of them should be serious too.
To check this I used Victoria’s road crash data. It has every injury crash police recorded from 2012 to 2025. That’s about 3,345 crashes a year on Melbourne’s local roads alone. I added ABS council boundaries and population so I could compare Port Phillip with councils that are similar but barely changed their limits.
One thing before we start. The data tells me the speed limit where each crash happened. It doesn’t tell me how fast anyone was actually going.
Before looking at Port Phillip I wanted to know if speed matters at all. It does. On local roads a pedestrian hit in a 40 km/h zone was killed or seriously injured 38% of the time. In a 60 km/h zone that jumps to 53%. Cyclists, motorcyclists and people in cars all show the same pattern.
# make the chart and give it a fixed height
p1 <- chart_1(zone_severity)
p1$height <- 560
# hidden text for screen readers, then the chart in a box that scrolls sideways on small screens
htmltools::tagList(htmltools::tags$p(class = "sr-only", alt_1), htmltools::div(class = "chart-scroll", p1))A dot and line chart in two panels, local roads and arterial roads, shows the share of injury crashes that were fatal or serious in each speed zone from 30 or 40 to 80+ km/h. It has one line each for pedestrians, cyclists, motorcyclists and vehicle occupants. In every group the share is higher in the fastest zones than in the slowest. On local roads a pedestrian crash was fatal or serious 38% of the time in a 40 km/h zone and 53% in a 60 km/h zone. Faster zones go with more serious crashes. The chart compares different streets.
To use it, just click a dot to show one road user in both panels. Double click to bring the others back.
Note. A crash is fatal or serious when someone in it was killed or seriously injured. Each crash is counted once under its most vulnerable road user. The bars on each dot show the range the real share probably sits in (95% interval). Faded points are based on fewer than 100 crashes. 30 km/h zones are grouped with 40 km/h. Data: 116,572 injury crashes on Melbourne local and arterial roads, 2012 to 2025. Source: Department of Transport and Planning (2026), Victoria road crash data, DataVic, CC BY 4.0.
These are different streets so this doesn’t prove the lower limit caused the difference. A busy shopping strip and a quiet back street aren’t the same. But this is the whole reason for lowering limits. If Port Phillip’s change worked I’d expect to see it in the crash numbers.
The speed zone maps don’t show when each street changed. So I used the crash data itself. Every crash records the speed limit where it happened. When more of a council’s crashes are in 40 km/h zones it’s a good sign more of its streets are 40 km/h.
# make the chart and give it a fixed height
p2 <- chart_2(council_summary)
p2$height <- 820
# hidden text for screen readers, then the chart in a box that scrolls sideways on small screens
htmltools::tagList(htmltools::tags$p(class = "sr-only", alt_2), htmltools::div(class = "chart-scroll", p2))A horizontal bar chart shows the change in the share of local road crashes in 40 km/h zones for each of 31 Melbourne councils, from 2012 to 2016 to 2022 to 2025. The bars are sorted from the biggest rise to the smallest. Port Phillip in vermillion has the longest bar. Its share went from 13% to 45%, a rise of 32 percentage points. The three main comparison councils in blue rose by 5.3 points or less. Port Phillip changed far more than the councils it is compared with.
How to use it: use the buttons to show all councils or only Port Phillip and its comparison councils. Hover a bar for the numbers.
Note. The share is the percentage of a council’s local road crashes that happened in a 40 km/h zone, with 30 km/h zones included and unknown zones left out. Bars start at zero. “(main)” and “(wider)” mark the comparison councils. Source: Department of Transport and Planning (2026), Victoria road crash data, DataVic, CC BY 4.0. Council distances: Australian Bureau of Statistics (2025), council boundaries, CC BY 4.0.
In Port Phillip that share went from 13% to 45%. That’s a rise of 32 percentage points, the biggest of all 31 councils. Percentage points just means the plain difference between the two shares. The three councils I compare it with are Banyule, Brimbank and Whitehorse. None of them rose by more than 5.3 points.
So one council changed a lot and the others barely moved. That’s what makes this a fair test.
So did crashes fall? Yes. Port Phillip had 11% fewer local road crashes a year in 2022 to 2025 than in 2012 to 2016. But the comparison councils dropped 8% over the same years. And they hardly touched their limits.
# make the chart and give it a fixed height
p3 <- chart_3(group_yearly)
p3$height <- 700
# hidden text for screen readers, then the chart in a box that scrolls sideways on small screens
htmltools::tagList(htmltools::tags$p(class = "sr-only", alt_3), htmltools::div(class = "chart-scroll", p3))Two line charts share a year axis from 2012 to 2025. The top panel shows the share of local road crashes in 40 km/h zones for Port Phillip and a comparison group. The bottom panel shows local road crashes each year with 2012 to 2016 set to 100. The rollout years 2017 to 2019 and the COVID years 2020 and 2021 are shaded. Port Phillip's 40 km/h share climbs while the comparison stays low. Both crash lines fall by a similar amount: 11% in Port Phillip and 8% in the main comparison. Most of Port Phillip's drop happened in the comparison councils too.
To use it, just use the menu to switch between the main and wider comparison. Hover a point or a flat line for the numbers.
Note. In the bottom panel 100 means the same number of crashes as in 2012 to 2016 and 90 means 10% fewer. Flat lines show the 2022 to 2025 average. The main comparison is Banyule, Brimbank and Whitehorse. The wider comparison is 9 councils within 20 km of the CBD. Source: Department of Transport and Planning (2026), Victoria road crash data, DataVic, CC BY 4.0. Population: Australian Bureau of Statistics (2026), Regional population, CC BY 4.0.
To compare councils of different sizes I set each one’s 2012 to 2016 level to 100. So 90 means 10% fewer crashes than before. The top panel shows Port Phillip pulling away into 40 km/h zones. The bottom panel shows crashes in both groups moving almost together. Most of the drop was happening everywhere. Only a small part of it could be down to the new limits.
I left out 2017 to 2019 because that’s when the limits were changing. 2020 and 2021 are shaded because COVID kept a lot of people off the roads.
Maybe lower limits don’t stop crashes but make them less serious. Figure 1 would suggest that. Before the change 39% of Port Phillip’s local road crashes killed or seriously injured someone. After the change it was 38%. The comparison councils actually dropped more, from 33% to 31%.
# make the chart and give it a fixed height
p4 <- chart_4(severity_periods)
p4$height <- 540
# hidden text for screen readers, then the chart in a box that scrolls sideways on small screens
htmltools::tagList(htmltools::tags$p(class = "sr-only", alt_4), htmltools::div(class = "chart-scroll", p4))A grouped bar chart with 95% interval lines shows the share of local road crashes that were fatal or serious in 2012 to 2016 and 2022 to 2025. It covers Port Phillip, the main comparison, the wider comparison and all Melbourne local roads. Port Phillip went from 39% to 38%. The main comparison went from 33% to 31%. Port Phillip's crashes were no less serious after the change. The interval lines overlap for every group.
To use it: hover a bar for its share, its range and the number of crashes.
Note. Striped bars are 2012 to 2016 and solid bars are 2022 to 2025. The black lines show the range the real share probably sits in (95% interval). The axis starts at 0%. The share fell across Melbourne after 2021 too, from 35.6% to 31.6%, so it’s best to compare the groups with each other. Source: Department of Transport and Planning (2026), Victoria road crash data, DataVic, CC BY 4.0.
The thin lines on each result show the range the real figure probably sits in. They overlap for every group. So the data can’t tell Port Phillip apart from the rest.
One last check. What if Port Phillip’s small extra drop was just chance? To test this I ran the same comparison on 9 other councils as if each of them had lowered its limits. If Port Phillip’s result was real it should stand out from theirs.
# make the chart and give it a fixed height
p5 <- chart_5(placebo, later_change)
p5$height <- 580
# hidden text for screen readers, then the chart in a box that scrolls sideways on small screens
htmltools::tagList(htmltools::tags$p(class = "sr-only", alt_5), htmltools::div(class = "chart-scroll", p5))A ranked dot chart shows 10 councils by how much more their crashes fell than the other comparison councils, with a line at zero. Port Phillip in vermillion has a gap of -4.4 points and comes 4th of 10. Gaps run from -11.7 to 27.2. A button switches to councils that moved into 40 km/h zones later. Their pooled gap is 0.9 points. Port Phillip's result is ordinary next to councils that barely changed.
Tse it: use the buttons to switch to the councils that changed later. Hover a dot for the numbers.
Note. The gap is how much a council’s crashes changed from 2012 to 2016 to 2022 to 2025, minus the change in the other comparison councils. It is in index points where 100 is the 2012 to 2016 level. Banyule’s +27 is a real rise in recorded crashes, mostly in 2024 and 2025 (76 a year against 58 in 2012 to 2016). All of that rise is in minor injury crashes, and its fatal and serious crashes fell 13%. The later councils are Merri-bek, Maribyrnong and Boroondara, compared with the main comparison from 2015 to 2019 to 2023 to 2025. Each has 57 to 145 local road crashes a year. Source: Department of Transport and Planning (2026), Victoria road crash data, DataVic, CC BY 4.0.
It doesn’t. Port Phillip comes 4th out of 10. That means 3 councils that barely changed their limits saw bigger drops than Port Phillip did. Brimbank’s crashes fell 11.7 points more than the others without any big change to its limits.
I also looked at councils that moved into 40 km/h zones later. Their crashes moved 0.9 points compared with the others. That’s next to nothing.
Lowering the limit on its own hasn’t made a noticeable difference to crashes in Port Phillip. Speed clearly matters for how badly people get hurt. But when Port Phillip moved a big part of its streets to 40 km/h its crashes didn’t drop any more than in councils that left theirs alone. They weren’t any less serious either.
I want to be fair to the new limits though. The data only shows the posted limit, not how fast people drive. If drivers kept doing 50 in a 40 zone then nothing would change. Lower limits also tend to go where lots of people walk, so Port Phillip was never a perfect match for the other councils. And with about 101 crashes a year a drop would need to be around 8% to stand out from the normal ups and downs.
So maybe a lower number on a sign isn’t enough. What would actually get drivers to slow down? More speed cameras? Safer crossings and more room for people walking? Narrower streets that make you drive slower without thinking about it? That’s where I’d look next. Next time I walk past a 40 sign in St Kilda I’ll be wondering how many cars are really doing 40.
I used three public sources. The crash data is the Victoria road
crash data file from DataVic. I read it into R with readr.
The council boundaries are the ABS 2025 council shapefile, read with
sf. The population is the ABS regional population table,
read with readxl. All three are saved in
data/raw/ exactly as I downloaded them.
The data has no record of when each street’s limit changed. So I used the share of a council’s local road crashes that happened in 40 km/h zones. When that share goes up it means more of the council’s streets are 40 km/h. About 9% of local road crashes have no speed zone recorded. I left them out of the shares but kept them in the crash counts.
The file has 202,297 crashes. I kept full years from 2012 to 2025, which took out 228 crashes from 2026. I kept Melbourne only, which took out 59,007 more. I also took out 6 councils with fewer than 20 local road crashes a year (65 crashes). They sit just over the edge of Melbourne. Moreland changed its name to Merri-bek, so I joined the two into one council (5,801 crashes). That left 142,997 crashes. For Figure 1 I also left out 257 crashes with no road user recorded.
I picked the comparison councils by rules before I looked at any crash results. The main comparison is councils within 20 km of the CBD. Each has at least 20 local road crashes a year. Each has a 40 km/h share under 15% on average. And each share rose by no more than 5 points from 2012 to 2016 to 2023 to 2025. That gave me Banyule, Brimbank and Whitehorse. The wider comparison allows a rise of up to 10 points. That gave me 9 councils. Figure 2 uses 2022 to 2025 as its after period to match the other figures. On that measure Banyule’s rise is 5.3 points against 4.6 on the rule’s years.
Before is 2012 to 2016. I left out 2017 to 2019 because that’s when Port Phillip’s limits were changing. After is 2022 to 2025. 2020 and 2021 are the COVID years. I shaded them and checked the results with and without them. To show crashes against population I used rates per 10,000 residents. Those rates don’t count visitors, and that matters in a council like Port Phillip.
I built the story on Mannon’s four parts from my course textbook (Data Visualisation: From Theory to Practice, n.d.). The opening and Figure 1 set it up. Figures 2 to 4 are the supporting facts. Figure 5 and the answer at the end are the main insight. The last paragraph is where I’d look next.
Every chart has one interaction with one job. I named each one with Yi et al.’s types (as cited in Data Visualisation: From Theory to Practice, n.d.). Figure 1 uses select. Clicking a road user shows it alone in both panels. Figure 2 uses filter. The buttons cut the list down to Port Phillip and its comparison councils. Figures 3 and 5 use reconfigure. The menu and buttons swap the comparison or the test. All five charts use elaborate through the hover text.
I followed the Evergreen and Emery checklist (as cited in Data Visualisation: From Theory to Practice, n.d.). Each chart title states what I found, with numbers worked out in R. Labels sit next to the data and there is no legend. Bars start at zero. There are no dual axes and the gridlines are light. Figures 1 and 3 use panels side by side or stacked so they’re easy to compare, which is one of the multivariate options in Chapter 6.
The colours come from the Okabe-Ito colourblind safe palette in Chapter 4. Port Phillip is always vermillion and the main comparison is always blue. I never use colour on its own. Shapes, stripes, labels and hover text carry the same information.
Baglin, J. (2026). Data visualisation: From theory to practice [Course textbook]. RMIT University.
City of Port Phillip. (n.d.). Speed limits. https://www.portphillip.vic.gov.au/council-services/traffic-roads-and-transport/speed-limits
Lawrence, B., Fildes, B., Thompson, L., Cook, J., & Newstead, S. (2020). Evaluation of the 30km/h speed limit trial in the City of Yarra, Melbourne, Australia. Traffic Injury Prevention, 21(sup1), S96–S101. https://doi.org/10.1080/15389588.2021.1895990
Rosén, E., & Sander, U. (2009). Pedestrian fatality risk as a function of car impact speed. Accident Analysis & Prevention, 41(3), 536–542. https://doi.org/10.1016/j.aap.2009.02.002
Segel, E., & Heer, J. (2010). Narrative visualization: Telling stories with data. IEEE Transactions on Visualization and Computer Graphics, 16(6), 1139–1148. https://doi.org/10.1109/TVCG.2010.179
Sievert, C. (2020). Interactive web-based data visualization with R, plotly, and shiny. Chapman and Hall/CRC. https://plotly-r.com
World Health Organization. (2023). Speed management: A road safety manual for decision-makers and practitioners (2nd ed.). https://www.who.int/publications/m/item/speed-management--a-road-safety-manual-for-decision-makers-and-practitioners.-2nd-edition
Yi, J. S., Kang, Y. A., Stasko, J., & Jacko, J. A. (2007). Toward a deeper understanding of the role of interaction in information visualization. IEEE Transactions on Visualization and Computer Graphics, 13(6), 1224–1231. https://doi.org/10.1109/TVCG.2007.70515
I used Claude (Anthropic) to assist me with the assignment process. I used Claude to find relevant web articles on the recently introduced road speed limit regulations. I also used it to figure out the coding errors I made during development and then checked them against the course materials before I changed anything. I also used Claude to suggest some minor changes to the plots to ensure they fit the screen properly, and to enhance their resolution. I compared its suggestions to my own understanding and cross-referenced it with relevant course materials like Data Wrangling and Applied Analytics from last semester.
I independently wrote, executed and verified all code in RStudio, and compared the final results against my own hypotheses before incorporating them into the report. I take full responsibility for the direction, design, methodology, coding, analytical decisions and final visualisations presented in this report.