Python Clustering and K-Means

Group unlabelled data with k-means, scale features first, compare cluster counts and describe clusters in their original units.

Lesson 98 of 107Advanced13 min read

Clustering groups similar observations together without being told what the groups are. K-means is the most widely used clustering algorithm: you choose the number of clusters, k, and it places k centres so that each observation belongs to its nearest centre and the points in each cluster are as close to their centre as possible.

Python
from sklearn.cluster import KMeans
X = [[1, 2], [2, 1], [9, 10], [10, 9]]       # visits per week, hours per visit
model = KMeans(n_clusters=2, n_init=10, random_state=0).fit(X)
print(model.labels_)                          # cluster number for each member

This lesson explains when clustering is the right tool, how k-means works, why feature scaling and the choice of k change the result, and how to judge whether clusters mean anything. The examples segment members of a community gym by how they use it. It's part of the ML track that begins with introduction to machine learning.

Unsupervised grouping

Clustering is unsupervised: there's no target column and no right answer to check against. You use it to explore structure, such as "are there distinct patterns in how members use the gym?", or to create segments for planning, such as timetables or targeted communications.

What counts as "similar" is entirely defined by the features you choose. Cluster members on visits per week and session length and you get usage patterns; add age and you get something different. Decide on features from the question you're asking, and exclude anything irrelevant or sensitive.

The algorithm returns cluster numbers, 0, 1, 2..., which carry no meaning by themselves. Cluster 0 isn't "the best" or "the first"; rerunning with different settings can swap the numbers. Meaning comes from describing each cluster afterwards, for example "frequent short visits" versus "occasional long sessions".

K-means objective

K-means alternates two steps until the assignments stop changing:

  1. Assign each point to its nearest centre.
  2. Update each centre to the mean of the points assigned to it.

It aims to minimise inertia: the sum of squared distances from each point to its centre. Because the starting centres are chosen randomly, different starts can end in different solutions; n_init=10 runs ten starts and keeps the best, and random_state makes the result repeatable.

Python
model = KMeans(n_clusters=3, n_init=10, random_state=0).fit(X)
print(model.cluster_centers_)   # one centre per cluster
print(model.inertia_)           # total within-cluster squared distance
print(model.predict([[4, 1.5]]))  # assign a new member to the nearest centre

K-means works best when clusters are roughly round and of similar size. It struggles with elongated, nested or very unequal clusters, and every point is forced into some cluster, outliers included. Algorithms such as DBSCAN (density-based) and Gaussian mixtures handle other shapes when k-means doesn't fit.

Scaling and choices

Three choices change k-means results:

  • Feature scale: k-means uses Euclidean distance, so a feature measured in minutes (0 to 120) outweighs one counted in visits (0 to 7). Standardise features first, inside a pipeline.
  • The number of clusters, k: you must choose it.
  • Initialisation: use n_init greater than 1 and fix random_state.

To compare values of k, look at two measures:

Python
from sklearn.metrics import silhouette_score
for k in [2, 3, 4]:
    km = KMeans(n_clusters=k, n_init=10, random_state=0).fit(X_scaled)
    print(k, round(km.inertia_, 1), round(silhouette_score(X_scaled, km.labels_), 2))

Inertia always falls as k grows, since more centres sit closer to the points, so look for an "elbow" where improvement levels off. The silhouette score (from −1 to 1) measures how much closer points are to their own cluster than to the next one; higher is better. Neither number alone decides k: a slightly lower-scoring solution that people can act on can be the more useful one.

Evaluation and meaning

Without labels, judge clusters by:

  • Separation: silhouette score and how distinct the centres are.
  • Stability: do similar clusters appear with different random starts or on a different sample of members?
  • Interpretability: can you describe each cluster in plain language, in original units?
Python
import pandas as pd
summary = members.assign(cluster=labels).groupby("cluster")[["visits", "minutes"]].mean()

Describing clusters by their average visits and minutes, not by scaled values, makes them understandable to the people who will use them.

Treat clusters as descriptions of patterns in data, not as judgements about people. "Members in cluster 2 rarely visit" may reflect shift work or childcare, not lack of motivation. Using clusters to deny services or make assumptions about individuals is a misuse; use them to ask better questions and to design offers people can choose.

Independent practice and a worked check

Task: explore gym visit clusters with scaled features, several cluster counts and a careful interpretation of their limits.

Python
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

members = [[1, 90], [1, 80], [2, 85], [5, 30], [6, 35], [5, 25],
           [3, 60], [4, 55], [3, 65], [6, 30], [1, 95], [4, 60]]
for seed in [0, 1, 2]:
    pipe = make_pipeline(StandardScaler(), KMeans(n_clusters=3, n_init=10, random_state=seed))
    labels = pipe.fit_predict(members)
    X = pipe[0].transform(members)
    print(f"seed {seed}: sizes {sorted([list(labels).count(c) for c in set(labels)])}, "
          f"silhouette {silhouette_score(X, labels):.2f}")

If cluster sizes and silhouette scores agree across seeds, the grouping is stable. Write one sentence per cluster in original units and one sentence on limits, such as "based on 12 members over one month". For the worked check: do k-means cluster labels have inherent category meanings? No. Meaning comes from describing the clusters afterwards.

Reference and next practice

scikit-learn's clustering guide compares k-means with other algorithms, and silhouette analysis shows how to choose k. Continue with the Python examples library and practice problems. Practise with the Python exercises and Python quiz.

Clustering and K-Means Summary

  • Unsupervised grouping: Clustering groups observations by selected feature relationships without known target labels.
  • K-means objective: K-means assigns observations to centers and seeks small within cluster squared distances.
  • Scaling and choices: Feature scale, cluster count and initialization affect the result.
  • Evaluation and meaning: Use stability, separation and domain interpretation to assess useful grouping.

Clustering and K-Means Examples

Each example shows the code, the output it produces and what each part does.

Example 1

Clustering and K-Means in a small program

Python
from sklearn.cluster import KMeans
X = [[1, 2], [2, 1], [9, 10], [10, 9]]
model = KMeans(n_clusters=2, random_state=3, n_init=10).fit(X)
centers = sorted([tuple(round(float(v), 1) for v in center) for center in model.cluster_centers_])
print(centers)
Output
[(1.5, 1.5), (9.5, 9.5)]
Line-by-line explanation
  1. Line 2Four members: two low-usage and two high-usage.
  2. Line 3K-means with two clusters, ten random starts and a fixed seed.
  3. Lines 4 to 5Sorting the rounded centres gives a stable display: each centre is the mean of its two members.
Example 2

Scaling, choosing k and describing clusters

  • k = 3 shows the inertia elbow (6.3 to 1.2, then only 0.9) and the highest silhouette score, matching three clear patterns: occasional long sessions, regular hour-long visits and frequent short visits.
Python
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.preprocessing import StandardScaler

# visits per week, minutes per visit
members = [[1, 90], [1, 80], [2, 85], [5, 30], [6, 35], [5, 25],
           [3, 60], [4, 55], [3, 65], [6, 30], [1, 95], [4, 60]]
X = StandardScaler().fit_transform(members)

for k in [2, 3, 4]:
    km = KMeans(n_clusters=k, n_init=10, random_state=0).fit(X)
    print(f"k={k} inertia {km.inertia_:5.1f} silhouette {silhouette_score(X, km.labels_):.2f}")

km = KMeans(n_clusters=3, n_init=10, random_state=0).fit(X)
for cluster in sorted(set(km.labels_)):
    rows = [m for m, label in zip(members, km.labels_) if label == cluster]
    visits = sum(r[0] for r in rows) / len(rows)
    minutes = sum(r[1] for r in rows) / len(rows)
    print(f"{len(rows)} members: {visits:.1f} visits/week, {minutes:.0f} min/visit")
Output
k=2 inertia   6.3 silhouette 0.53
k=3 inertia   1.2 silhouette 0.69
k=4 inertia   0.9 silhouette 0.67
4 members: 3.5 visits/week, 60 min/visit
4 members: 5.5 visits/week, 30 min/visit
4 members: 1.2 visits/week, 88 min/visit
Line-by-line explanation
  1. Line 8Standardising stops minutes, with their larger numbers, from dominating the distance.
  2. Lines 10 to 12Inertia falls as k grows; the silhouette score helps judge whether extra clusters are genuinely distinct.
  3. Lines 15 to 19Each cluster is described by its average in original units, which is what makes it interpretable.

Common Clustering and K-Means Mistakes

Clustering unscaled features

Don't
KMeans(n_clusters=3).fit(members)          # minutes (25-95) swamp visits (1-6)
Do
from sklearn.pipeline import make_pipeline
make_pipeline(StandardScaler(), KMeans(n_clusters=3, n_init=10, random_state=0)).fit(members)

Treating cluster numbers as meaningful labels

Don't
print("Cluster 0 are our best members")   # numbers are arbitrary and can swap
Do
for c in sorted(set(labels)):
    print(c, summary.loc[c].round(1).to_dict())   # describe, then name

Clustering and K-Means in Real Projects

Clustering in practice

Retailers segment customers by purchase patterns to plan stock and promotions, city planners group neighbourhoods by transport use, and scientists cluster gene-expression profiles or galaxy measurements. Clustering also compresses data, for example reducing an image to k colours, and helps find anomalies, which sit far from every centre.

Good practice is consistent across fields: choose features from the question, scale them, compare several k values and random starts, describe clusters in original units, check stability, and present results as patterns to investigate rather than fixed categories.

Clustering and K-Means FAQ

How do I choose the number of clusters in k-means?

Fit several values of k and compare inertia (look for an elbow where improvement flattens) and silhouette scores (higher is better), then check which solution gives clusters you can describe and use. There's rarely one mathematically correct k.

Do I need to scale data before k-means?

Usually, yes. K-means uses distances, so features with larger numeric ranges dominate. Standardise features unless they already share the same units and scale.

Why does k-means give different results each run?

Its starting centres are random, and different starts can converge to different solutions. Set n_init to run several starts and keep the best, and fix random_state for reproducible results.

What is the difference between clustering and classification?

Classification is supervised: it learns from examples with known labels to predict labels for new data. Clustering is unsupervised: it finds groups in unlabelled data, and people decide what those groups mean.

When should I not use k-means?

When clusters are elongated, nested or very different in size or density, when there are many outliers, or when features are categorical. Consider DBSCAN, Gaussian mixture models or hierarchical clustering instead.

Clustering and K-Means Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Multiple choiceeasy

Do K-means cluster labels have inherent category meanings?

Multiple choicemedium

Which review concern is valid for clustering and k-means?

Clustering and K-Means Quiz

2 questions to check what you learned.

  1. Do K-means cluster labels have inherent category meanings?

    • Yes
    • No
    • Python ignores the distinction
  2. Which statement correctly describes scaling and choices?

    • Feature scale, cluster count and initialization affect the result.
    • Only the example output matters, not the rule
    • Every operation has the same behavior