The same 120 customers appear in both modes. Here nothing is labelled, so there is no answer sheet. k-means splits the cloud into however many groups you ask for, and the only honest questions are whether the split is stable and whether anyone can use it. Set k, then walk the loop one step at a time.
WCSS at convergence, k = 3
20,467
squared index points
Refit agreement, adjusted Rand index
0.98
1.00 is the same split, 0.00 is chance
Both features are synthetic index numbers, built to run 0 to 100 with comparable spread, about 23 index points each across this cloud, and with no deliberate difference in importance. That is why a step of one carries about the same weight on either axis here and this cloud needs no rescaling. Shared bounds on their own would not buy that. Two indices can both run 0 to 100 and still have spreads of 2 and 30, or be meant to matter unequally. In real work the scaling decision turns on units, spread, outliers and what the business thinks each feature is worth, and getting it wrong lets one feature decide every distance on its own.
Converged WCSS at every k, and why WCSS cannot choose k
The best attainable WCSS cannot rise as k rises, because splitting one group in two always matches the old total and usually beats it. It falls at every step here, so picking the lowest bar would pick k = 6 every time. That is why the lowest WCSS is not an answer to the question of how many groups there are.
WCSS at this step 20,467Groups 3Smallest group 36 customers
Number of groups, k3 groups
Step 7 of 7. The assignment repeated itself, so the loop has stopped.
Three tests the concept page sets for a clustering result
Do the groups differ in ways a marketing team can act on. That is a business judgement and this widget does not make it. The group table below gives the raw material.
Do they survive refitting on a different half of the customers. Measured here. An adjusted Rand index of 0.98 at k = 3, against 1.00 for the same split and 0.00 for chance.
Can a person describe each group in a sentence. Also a person's job, from the centres and sizes in the table.
The 3 groups at step 7 of 7. Centres are index points on the same 0 to 100 scale as the axes. Sizes read an em dash until the first assign step, because before it no customer belongs to a group.
Group
Customers
Centre spend
Centre visits
Marker
Group 1
44
26.6
34.0
circle
Group 2
36
69.1
27.1
square
Group 3
40
70.2
74.7
triangle
At k = 3 the loop has stopped, and the within-cluster sum of squares stands at 20,467 squared index points. Group sizes are 44, 36, 40. WCSS measures fit and nothing else. The refit test is the only number here that speaks to whether the same split comes back from a different half of the file, and even that is reproducibility rather than proof that the groups are real. No clustering run can supply that proof. The adjusted Rand index between this split and the refits is 0.98, 1.00 on the even-indexed half and 0.95 on the odd-indexed half. It reads both partitions, so a pair this k separated and a refit merges counts against the score and not only a pair that was broken, and it is corrected for the agreement two unrelated splits reach by chance, which is why it can be compared across different k with more confidence than a raw count of pairs held together. Across k = 2 to 6 the highest agreement here is at k = 3 on 0.98, and the lowest WCSS is at k = 6. The two criteria point at different k here, and only one of them is about whether the split reproduces at all.
Stylised cloud, not observed customers, generated from three seeded blobs. The generator's own blob membership is never shown, because unsupervised work has no such key. The halves are the even-indexed and odd-indexed records, and the blobs were interleaved when the cloud was built so that split is not a split on blob. The run on screen is the best of 6 seeded k-means++ starts for this k, judged on final WCSS, so the same k always gives the same answer. A group that ends an assign step with no customers keeps its centre where it is and is reported as empty. That happens at no step of any run shown here, and the rule is in the code so the recentre step can never divide by zero.