Written and maintained by CASRAI Editorial Board
Last updated
K-means clustering is an unsupervised method that splits a set of observations into k groups so that each observation belongs to the group whose mean (its centroid) is nearest. This guide gives the objective function with every symbol defined, a six-number example worked by hand in full, a table for reading the output, the assumptions that most often break it, and R and Python code that reproduce the hand calculation.
What is k-means clustering?
K-means clustering divides N samples into K disjoint clusters, each described by the mean of the samples assigned to it. The scikit-learn documentation states that the algorithm “clusters data by trying to separate samples in n groups of equal variance, minimizing a criterion known as the inertia or within-cluster sum-of-squares”, and that it requires the number of clusters to be specified in advance.
The method is unsupervised: there is no outcome variable and no labelled training set. Because the clusters are disjoint, each observation lands in exactly one cluster. Researchers use it to explore structure in survey responses, instrument readings or other numeric measurements. For a contrast between k-means and hierarchical clustering with a software click-path, see cluster analysis in SPSS: hierarchical vs k-means. For where clustering sits among learning methods, see supervised vs unsupervised learning and what is machine learning.
K-means clustering formula (the within-cluster sum of squares)
The quantity k-means minimizes is the sum, over all samples, of the squared distance from each sample to the nearest centroid:
Σi=0..N-1 minμj ∈ C ‖xi − μj‖²
- N: the number of samples (observations).
- xi: the i-th sample, a vector with one value per variable.
- C: the set of K clusters, and μj the mean (centroid) of the samples in cluster j.
- ‖xi − μj‖²: the squared Euclidean distance between a sample and a centroid.
- min: each sample is charged only for its nearest centroid.
This criterion is called inertia or the within-cluster sum of squares (WCSS). R’s kmeans reports it as tot.withinss, alongside totss (the total sum of squares) and betweenss, which equals totss minus tot.withinss.
The standard procedure for minimizing it is Lloyd’s algorithm: (1) choose K initial centroids, in the simplest case K samples drawn from the data; (2) assign every sample to its nearest centroid; (3) recompute each centroid as the mean of its assigned samples; (4) repeat steps 2 and 3 until the centroids stop changing by more than a small threshold.
K-means clustering example worked by hand
Take six one-dimensional observations: 1, 2, 4, 9, 10, 12, and ask for K = 2 clusters. Start with the first two observations as centroids: A = 1 and B = 2.
Iteration 1
Assign each value to the nearer centroid. The value 1 is at distance 0 from A, so it joins A. The value 2 is at distance 0 from B, so it joins B. The value 4 is 3 from A and 2 from B, so it joins B. The values 9, 10 and 12 are closer to B, so they join B. Cluster A = {1}; cluster B = {2, 4, 9, 10, 12}.
Recompute the centroids: A = 1; B = (2 + 4 + 9 + 10 + 12) / 5 = 37 / 5 = 7.4. The within-cluster sum of squares around the new centroids is 0 for A, and for B (2 − 7.4)² + (4 − 7.4)² + (9 − 7.4)² + (10 − 7.4)² + (12 − 7.4)² = 29.16 + 11.56 + 2.56 + 6.76 + 21.16 = 71.2.
Iteration 2
With centroids A = 1 and B = 7.4: the value 1 is at distance 0 from A; 2 is 1 from A and 5.4 from B, so A; 4 is 3 from A and 3.4 from B, so A; 9 is 8 from A and 1.6 from B, so B; 10 and 12 also go to B. Cluster A = {1, 2, 4}; cluster B = {9, 10, 12}.
New centroids: A = 7 / 3 = 2.333; B = 31 / 3 = 10.333. The sum of squares is now 1.778 + 0.111 + 2.778 = 4.667 for A and 1.778 + 0.111 + 2.778 = 4.667 for B, a total of 9.333, down from 71.2.
Iteration 3
Reassigning with centroids 2.333 and 10.333 leaves every value in the same cluster, so the centroids do not move and the algorithm has converged. The total sum of squares of the six values around their grand mean (6.333) is 105.333, so the between-cluster sum of squares is 105.333 − 9.333 = 96.0, which is 91.1% of the total.
Reading the result
| Output | What it tells you | Caution |
|---|---|---|
Inertia / tot.withinss (9.333 in the example) |
Total squared distance from samples to their centroids; lower is better and zero is optimal. | It is not a normalized metric, so it cannot be compared across datasets or variable scalings, and it always falls as K rises. |
betweenss / totss (96.0 / 105.333 in the example) |
The share of total variation that the cluster means account for. | Computed from the totals R reports (totss and tot.withinss). |
To choose K, a common approach is to run the algorithm for several values of K and plot the within-cluster sum of squares against K, then look for the point where the curve flattens (the elbow method). The Dunn index and the silhouette score are other measures used to compare solutions.
Assumptions and common mistakes
- Convex, isotropic clusters. Inertia assumes clusters are convex and isotropic, so k-means responds poorly to elongated clusters or manifolds with irregular shapes.
- K must be specified. The algorithm does not choose the number of clusters; the analyst does.
- Local minima. Given enough time k-means will always converge, but possibly to a local minimum that depends on the starting centroids. Run it several times from different initializations. scikit-learn offers
k-means++initialization, which starts the centroids generally far from each other, and R’snstartargument sets how many random starting sets are tried. - Unscaled variables. Distances are Euclidean, so a variable measured on a large scale dominates the result. Standardize variables measured on different scales before clustering (a general consequence of using squared Euclidean distance).
- High dimensions. In very high-dimensional spaces Euclidean distances inflate; scikit-learn notes that running PCA before k-means can alleviate this.
- Very large datasets. A mini-batch variant exists for large numbers of samples.
How to report it
A reader should be able to repeat the analysis from the methods text. Report the software and version, the variables and any scaling, the distance measure, the value of K and how it was chosen, the initialization method and number of random starts, the random seed, and the final within-cluster sum of squares. An example sentence in that style:
We grouped the 6 observations into K = 2 clusters using k-means (Lloyd’s algorithm, Euclidean distance, one start with initial centroids at the first two observations). The algorithm converged after three iterations with centroids at 2.33 and 10.33 and a total within-cluster sum of squares of 9.33 (96.0 of 105.33 total, 91.1%).
For a real study, replace the single start with the number of random starts and the seed you used, and cite the software in your reference list according to the style guide your journal requires.
K-means in R and Python
Python (scikit-learn)
import numpy as np
from sklearn.cluster import KMeans
x = np.array([1, 2, 4, 9, 10, 12]).reshape(-1, 1)
km = KMeans(n_clusters=2, init=np.array([[1.0], [2.0]]), n_init=1).fit(x)
print(km.labels_) # [0 0 0 1 1 1]
print(km.cluster_centers_) # 2.333 and 10.333
print(km.inertia_) # 9.333 (within-cluster sum of squares)
For real data, use the default init='k-means++' and several starts instead of fixed centroids.
R (stats::kmeans)
x <- c(1, 2, 4, 9, 10, 12)
set.seed(1)
fit <- kmeans(x, centers = 2, nstart = 25)
fit$centers # 2.333 and 10.333 (cluster order may differ)
fit$tot.withinss # 9.333
fit$betweenss # 96
fit$totss # 105.333
The signature begins kmeans(x, centers, iter.max = 10, nstart = 1, algorithm = c("Hartigan-Wong", "Lloyd", "Forgy", "MacQueen"), ...); centers is either the number of clusters or a set of initial centres, and the default algorithm is Hartigan-Wong rather than the Lloyd procedure described above, so report which one you used.
FAQ
What is k-means clustering?
It is a method that partitions observations into K groups by repeatedly assigning each observation to the nearest group mean and recomputing the means, which minimizes the within-cluster sum of squares.
What does the k-means clustering formula minimize?
The sum of squared Euclidean distances between each observation and its nearest centroid, called inertia or WCSS.
Does k-means always find the best clustering?
No. It always converges, but possibly to a local minimum, so run it from several initializations and keep the run with the lowest within-cluster sum of squares.
Do I need to scale my variables first?
Yes when variables are on different scales, because the method uses squared Euclidean distance and large-scale variables will dominate.
Can inertia tell me the right number of clusters?
Not by itself. It is not normalized and decreases as K increases, so it is compared across values of K, for example in an elbow plot, alongside measures such as the silhouette score.
Sources
- scikit-learn User Guide, section 2.3.2 K-means, scikit-learn.org/stable/modules/clustering.html#k-means (checked 2026-10-29).
- R Documentation,
stats::kmeans, stat.ethz.ch/R-manual/R-devel/library/stats/html/kmeans.html (checked 2026-10-29). - IBM Think, What is k-means clustering? (elbow method, Dunn index, silhouette), ibm.com/think/topics/k-means-clustering (checked 2026-10-29).
- Worked-example arithmetic reproduced with scikit-learn 1.9.0 (checked 2026-10-29).








