Charts/Flow, tree and profile charts
Dendrogram
<Dendrogram /> · 10 examples
A tree that shows which rows are most alike, built by repeatedly merging the two closest groups.
Overview
Clustering has an awkward first question: how many clusters? K-means makes you answer before it starts, which is a bit like being asked to choose the number of chapters before writing the book. Hierarchical clustering sidesteps the problem by refusing to commit. It starts with every row on its own, merges the two most similar, then the next two, and keeps going until only one blob remains. The record of those merges is the dendrogram.
The word is Greek for "tree drawing", and the picture earns it. Leaves along the bottom are your rows. Every U-shaped join is one merge, and the height of the join is how far apart the two things being merged were. Tight pairs join low. Odd rows hold out and join high up, near the trunk, like the cousin who arrives at the party after dessert.
The best feature of a dendrogram is that you pick the cut afterwards. Slice it low and you get many small, very similar groups. Slice it high and you get a few big ones. The tree has the answer to every value of k at once, and the picture helps you see where the natural joints are: a long vertical gap before a merge means two groups that really are distinct.
Props
API
<Dendrogram data={animals} name={|a: &Animal| a.name} features={|a: &Animal| a.traits.as_slice()} clusters={3} />| Prop | Type | Default |
|---|---|---|
data | as above: one row per leaf | required |
name | Fn(&T) -> &str | required |
features | Fn(&T) -> &[f64]: the values compared between rows | required |
linkage | Linkage::Single, Complete, Average or Ward | Average |
clusters | usize: cut the tree into this many coloured clusters | 1 |
horizontal | bool: leaves down the side | false |
color | colour, when clusters is 1 | the first series colour |
value_axis | AxisConfig for the merge distance | from 0, labelled "Distance" |
class |
Rows are clustered by Euclidean distance, joining the two closest clusters again and again (the Lance–Williams method). The height of each join is the distance between the two clusters. Leaves are ordered so branches never cross. Links above the cut are drawn in the neutral colour.
Run them
10 examples
Press Run to load an example into the live render at the top of the page. Open one to read its code.
How to read it
- 01Find the leaves along the bottom (or the left, with
horizontal): each one is a row. Read the labels first. - 02Trace two leaves up to where they meet. The height of that join is the distance at which they became one group. Lower means more alike.
- 03Look for long vertical stretches with no merge. A long gap is a natural cut: the groups below it are well separated from each other.
- 04Use
clustersto colour the tree for a chosen cut. Links above the cut stay neutral, so the colours show you the groups at a glance. - 05Do not read left-to-right proximity as similarity. Only the joins carry meaning.
When to use it, and when not to
Reach for it when
- You want to group rows by similarity without choosing the number of groups first, and you want to see how the groups nest.
- The rows are few enough to label (up to a few hundred): countries, products, genes, patients, teams.
- You are exploring. A dendrogram is one of the quickest ways to find out whether your data has structure, or only has rows.
- You want to compare how different linkages group the same data. Switching one prop changes the tree and the story.
Skip it when
- The features are on wildly different scales and you have not normalised them. The tree will mostly reflect the biggest feature.
- You have thousands of rows. The labels cannot fit and the cubic cost starts to hurt. Cluster first with something else, or sample.
- You need to say how confident a grouping is. A dendrogram is a description of the merge order, not a hypothesis test.
- The rows have a natural order, like time. Use a line chart. Clustering them will scramble what you already know.
The math behind it
Distances between rows
Each row gives you a vector of numbers through the features function. Rows are compared by plain Euclidean distance. If a feature is missing or not finite for a pair, that coordinate is skipped for that pair, so a row with a hole is compared on what it has instead of dropping out. Nothing is rescaled: a feature measured in thousands will outvote one measured in tenths, so put features on similar scales yourself.
Merging: linkage
The algorithm starts with singleton clusters and, at every step, finds the pair of clusters and with the smallest gap and merges them into . What differs between linkages is how the gap from the new cluster to some other cluster is computed from the gaps that already exist. All four use the Lance-Williams update, so each step is a cheap formula on the old distances rather than a recomputation from the points.
Single keeps the minimum of the two old gaps and tends to chain. Complete keeps the maximum and keeps clusters tight. Average (the default) takes the size-weighted mean. Ward works on squared distances and minimises the growth in within-cluster variance. is the number of rows in .
Drawing the tree
The merge sequence is a binary tree with leaves and internal nodes. Leaves are ordered by a depth-first walk from the root, left child before right, and leaf in that order sits at position . Each internal node sits halfway between its children and at the height of its merge. For Ward the stored height is the square root of the squared gap, so it is in the same units as the data. A merge is drawn as a bracket: down from the node to each child's position.
The order of the walk is whatever the merge order gives. It is not re-arranged to put the most similar leaves side by side, so two similar rows can end up separated by an unrelated subtree. Heights, not left-right positions, carry the similarity.
Setting clusters to cuts the tree as if you had asked for groups: the last merges (the highest ones) are left neutral and everything below them is coloured by the group it belongs to. With (the default) there is nothing to cut and the whole tree is one colour. The work is cubic in the number of rows, so a few hundred is fine and ten thousand is not.
Real life usage
Seven stores that were secretly two
Mirela was the data analyst for a coffee roaster with seven small shops and one very strong opinion about oat milk. The operations director wanted one staffing plan per shop. The finance director wanted one plan for the whole company. The two of them had been having this conversation since March, and it had acquired the quality of a family tradition.
Mirela suspected the truth was in between, but suspicion is not a slide. She had hourly sales for each shop averaged into twelve numbers, one for each two-hour block over a typical day, and a growing feeling that some of the shops behaved more like each other than their addresses implied.
The task was to find out how many different kinds of shop there really were, without anyone having to pick the number in advance, because whichever number she picked would be the one the room argued about.
She normalised each shop's twelve numbers into shares of that shop's own day, so a busy shop and a quiet one with the same rhythm would look alike, and fed them to <Dendrogram> from zopra-charts with average linkage. Seven labelled leaves, six brackets, and one very obvious thing.
Five of the shops merged at tiny heights, almost on top of each other: the morning rush, a dip, a small afternoon bump. The other two joined each other low and everyone else very high. Those two were the shops by the university, which did not have a morning rush so much as an afternoon-into-evening one, with a long study-session tail.
She set clusters to two and the colours made it undeniable. The company ran two staffing patterns, not seven and not one. The operations director got a plan for the two campus shops, the finance director got a template for the other five, and the extra hours at the university shops cut walk-aways during the evening queue by about a fifth.
Both directors claimed to have been right all along. Mirela has stopped correcting them, and keeps the tree on her wall.
Pitfalls
- Scale decides everything. Euclidean distance on raw features gives the biggest unit all the votes. Scale to 0-10 or z-scores first.
- Linkage changes the tree. Single chains, complete keeps groups tight, average is a compromise, Ward makes compact even groups. If a conclusion survives all four, you can trust it more.
- Left-right closeness means nothing. Neighbouring leaves may be unrelated, because only the heights of the joins carry distance.
- Cutting is your decision.
clusterscolours a cut. It does not choose a good one. Look for the longest vertical gap before picking. - Cost grows with the cube of the row count. A few hundred rows is comfortable. Beyond that, reduce the data first.
From around the web