Skip to content

GEOSPATIAL ML · FULL STACK

Finding where Nashville's 911 calls cluster, on an interactive map

I clustered Metro Nashville's public 911 call data from 2024 into 131 hotspots with DBSCAN, weighted each call by how serious it is, and put the result on a map with location alerts. Nashville gets a lot of visitors, and I wanted them, and locals, to have a simple way to see which areas draw the most calls.

A map of Nashville drawn from 145,226 geocoded 2024 911 calls, with the 131 DBSCAN hotspots circled.

THE GAP

The data is public, but it doesn't tell a visitor where to be careful.

Metro Nashville publishes its 911 calls for service as open data. The 2024 export I used has 369,380 calls, from January 1 to November 14. Each has a call type and a time, and 39% have a location, rounded to about 100 meters.

That's a table, not an answer. To help someone deciding where to walk, it has to become areas with edges, ranked by how serious the calls inside them are.

01

Rows, not places

Each call is a row with a point. Nothing says where one busy area ends and the next begins.

02

Not all calls are equal

A shooting and a traffic violation are both one row. Counting rows treats them the same.

03

No fixed count

Nobody knows in advance how many hotspots a city has, so the method has to find that number itself.

WHAT IT DOES

A hotspot map for visitors and locals

A Python script turns the calls into hotspots once and saves them as JSON. A FastAPI backend serves them, and a React and TypeScript front end draws them on a Leaflet map with filters, location alerts and a route check. There's also a simpler Streamlit version for a quick look.

Weighted by seriousness

Each call scores 3, 2 or 1 by type, so shootings and robberies outweigh traffic violations and business checks.

A reason for every hotspot

Click a circle to see its severity, call count and a generated note naming its most common call types.

Alerts where you stand

With browser GPS on, the map warns you inside a hotspot's radius plus 50 meters. The check stays in your browser.

A route check

Enter two coordinates and it scores the straight line between them, plus three offset variants, against the hotspot circles.

HOW IT WORKS

From the map to a route check

  1. 1

    Open

    Every hotspot is a circle: red for High, orange for Medium, green for Low.

  2. 2

    Filter

    Hide the severity levels you don't need from the filter panel.

  3. 3

    Inspect

    Click a circle for its call count, severity and a short note on why.

  4. 4

    Locate

    Turn on GPS or type coordinates; a warning appears when you're inside a hotspot.

  5. 5

    Route

    Enter start and end coordinates to score the straight line and three variants.

SYSTEM DESIGN

Cluster once, serve a file

The heavy work happens once, offline: a script weights the calls, clusters them and writes hotspots.json. The API serves that file, and the map draws it.

RESULTS

What 145,226 calls turned into

145,226

2024 911 calls with usable coordinates, of 369,380

131

DBSCAN hotspots at a 400 m radius and 30 calls

87

of those 131 rated High by the severity rule

107,836

calls in one core cluster, 18.5 km in radius

That core cluster holds 78% of every call that landed in a hotspot.

WHAT IT TAUGHT ME

What it taught me

One radius can't fit a whole city. At 400 meters, DBSCAN chained the dense middle of Nashville into a single cluster of 107,836 calls, so the React map draws one High circle 18.5 km in radius over the center of town; the Streamlit version just hides it. The data has limits too: only 39% of calls have a location, it's rounded to about 100 meters, and a 911 call isn't a crime. The most common one is a general request for an officer. And the route check is a prototype: it scores straight lines, not streets.

BUILT WITH

  • Python
  • pandas
  • scikit-learn
  • FastAPI
  • React
  • TypeScript
  • Leaflet
  • Streamlit

Like what you see?

Thanks for reading. There's more where this came from.