Visual walkthrough — DBSCAN density-based clustering
This page rebuilds the whole idea of DBSCAN density-based clustering from nothing — no formulas assumed, no jargon borrowed. We start with dots on paper and a single question: "which dots belong together?" By the end, every DBSCAN rule will have been drawn before it was written.
Step 1 — Draw a bubble around one dot
WHAT. Pick any single dot . Draw a circle of a fixed radius around it. We call that radius (the Greek letter epsilon, pronounced "EP-si-lon"). It is just a number — a chosen size, like "3 centimetres."
WHY. To measure "crowdedness," we need a window. Without a window we could only compare a dot to the whole dataset (global), but crowds are a local thing — a dot is crowded relative to what's right next to it. The circle is that local window.
PICTURE. The red dot is . The circle is its personal-space bubble. Any dot falling inside or on the circle is a neighbour.

The vertical bars later mean "how many dots are in this collection" — a simple count.
Step 2 — Count the bubble to decide "dense or not"
WHAT. Count the dots inside the bubble: . Compare that count to a second chosen number, MinPts (minimum points). If the bubble holds at least MinPts dots, we crown a core point.
WHY. One neighbour proves nothing — even a lonely outlier will randomly have someone nearby. We need a threshold that separates "coincidentally close" from "genuinely in a crowd." MinPts is that bar.
PICTURE. Same bubble, now with the count written inside. Left: 5 dots, bar is 4 → core (red). Right: 2 dots, bar is 4 → not core.

The count ==includes itself==, so MinPts really means " plus 3 friends."
Step 3 — Chain the cores: reachability
WHAT. If is core and dot sits inside 's bubble, then is directly density-reachable from . Now hop: if is also core, look inside 's bubble and grab its neighbours too. Repeat. The crowd grows outward one bubble at a time.
WHY. A single bubble is small; a real cluster is bigger than any one radius. We stitch bubbles together only through core points, so the crowd can only spread through genuinely dense links — never leap across an empty gap.
PICTURE. Three overlapping bubbles centred on three core dots. The red path shows the chain : each next centre lives inside the previous bubble.

Step 4 — Three kinds of dots (cover every case)
WHAT. Every dot ends up as exactly one of three types:
- Core — bubble meets MinPts. (Step 2)
- Border — bubble is below MinPts, but it sits inside some core's bubble.
- Noise — below MinPts and touched by no core. A true outlier.
WHY. This triple exactly matches how a crowd looks: a dense centre (cores), a fuzzy rim (borders), and lonely stragglers (noise). Nothing is left unclassified — this covers all possibilities.
PICTURE. One cluster: red core dots in the middle, black border dots on the rim (each inside a core bubble but with a sparse own-bubble), and a lone black noise dot far away with an empty bubble.

Step 5 — Grow a full cluster from a seed
WHAT. Start at an unvisited dot. If it's core, open a new cluster and run a queue: pop a core, add all its bubble-mates to the cluster, and if any of those are also core, push their neighbours onto the queue. Keep draining the queue until it's empty — the cluster stops growing exactly where density dies.
WHY. We want each cluster maximal: it should swallow every dot that density can reach, no more, no less. The queue guarantees we never stop early (we keep expanding through cores) and never leap a gap (only cores add new dots).
PICTURE. A curved crescent of dots. The red frontier shows the cluster after a few queue steps; unclaimed dots ahead are grey, claimed dots behind are black. The frontier bends with the shape — this is why DBSCAN finds arbitrary shapes that K-means cannot.

Step 6 — The degenerate cases (never leave a hole)
WHAT. Three edge situations the reader must see:
- Tiny huddle below MinPts — two dots close together but only 2 of them, MinPts . Neither is core → both are noise, even though they touch.
- ε too large — every bubble swallows everything → one giant cluster, no noise.
- ε too small — no bubble reaches MinPts → every dot is noise, zero clusters.
WHY. These show the parameters are not decoration — they are the definition of "crowd." A reader who meets these mid-project would panic; here you see them on purpose.
PICTURE. Three mini-panels: (a) a 2-dot huddle both flagged noise; (b) a huge bubble covering all dots → one blob; (c) pinprick bubbles touching nobody → all noise.

Step 7 — Choosing ε with the k-distance elbow
WHAT. For every dot, measure the distance to its -th nearest neighbour (take ). Sort all those distances small-to-large and plot them. The curve stays flat, then kinks sharply upward — the elbow. Read off the height at the elbow; that height is a good .
WHY. Dots inside crowds have small -distances (friends are close); outliers have large ones. Sorting lines them up so the crowd-to-outlier transition appears as a single visible bend. Picking at the bend puts the boundary exactly between "dense" and "sparse."
PICTURE. The sorted k-distance curve: flat, low region on the left, a red circle marking the elbow, then a steep rise. A horizontal dashed line drops from the elbow to the value on the axis.

Finding those k-th neighbours fast is exactly the job of KD-Trees and Spatial Indexing; note that in very high dimensions the elbow blurs — the Curse of Dimensionality flattens all distances together.
The one-picture summary
Everything at once: one crescent grown from a core seed (red frontier), border dots on its rim, a lonely noise dot with an empty bubble off to the side, and a bubble of radius shown as the ruler that set the whole thing.

Recall Feynman retelling — say it like a story
I put a bubble of size around a dot and count who's inside. If the count meets my crowd-bar MinPts, that dot is a core — a leader. I then hop from core to core, and every dot inside a core's bubble joins the cluster; the ones on the rim (too few of their own neighbours) are borders, followers. I keep hopping through cores with a queue until no more cores are reachable, so the cluster grows exactly as far as the density lasts — which is why it can bend around a crescent while K-means can only draw circles. Dots that are neither cores nor touched by a core are noise — genuine loners. If two lonely dots huddle but don't reach MinPts, they're still noise. Make huge and everything fuses into one blob; make it tiny and everything becomes noise — so I pick from the elbow of the sorted k-distance plot, the spot where crowd-distances suddenly turn into outlier-distances. That's the whole algorithm: bubble, count, hop, stop where density stops.