Freedom Sale
Independence Day Special — Unlock the AI Path 70% off our most popular AI course · Limited time offer
--Days
--Hrs
--Min
--Sec
Claim Your Discount
✦ Intermediate ⏱ 40 min

🎯 Build Customer Segmentation with K-Means Clustering

🎯 What You'll Build

A customer segmentation model that groups shoppers into clusters by spending behaviour — with the Elbow Method, 2D scatter plots, and cluster profiling.

📋 What You'll Need

1

Load and explore the Mall Customers dataset

The dataset has 200 customers with age, income, and spending score.

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# Download from: https://www.kaggle.com/datasets/vjchoudhary7/customer-segmentation-tutorial-in-python
df = pd.read_csv('Mall_Customers.csv')
print(df.head())
print(df.describe())

# Feature engineering: use annual income and spending score
X = df[['Annual Income (k$)', 'Spending Score (1-100)']].values
2

Find the optimal number of clusters with the Elbow Method

Run K-Means for K=1 to 10 and plot inertia — the "elbow" shows the best K.

from sklearn.cluster import KMeans

inertias = []
K_range  = range(1, 11)

for k in K_range:
    km = KMeans(n_clusters=k, random_state=42, n_init=10)
    km.fit(X)
    inertias.append(km.inertia_)

plt.figure(figsize=(7,4))
plt.plot(K_range, inertias, 'bo-', linewidth=2)
plt.xlabel('Number of clusters (K)')
plt.ylabel('Inertia (within-cluster sum of squares)')
plt.title('Elbow Method — Finding Optimal K')
plt.xticks(K_range)
plt.grid(alpha=0.3)
plt.tight_layout()
plt.savefig('elbow_method.png', dpi=120)
plt.show()
print("Look for the 'elbow' — the point where inertia stops dropping sharply.")
3

Train the final model and visualise segments

K=5 is the elbow for this dataset — five clear customer segments.

from sklearn.cluster import KMeans
import numpy as np

K = 5
km = KMeans(n_clusters=K, random_state=42, n_init=10)
labels = km.fit_predict(X)
centers = km.cluster_centers_

# Assign cluster labels to the dataframe
df['Cluster'] = labels

COLORS = ['#e74c3c','#3b82f6','#22c55e','#f59e0b','#a855f7']
NAMES  = ['Careful', 'Standard', 'Target', 'Careless', 'Sensible']

plt.figure(figsize=(8,6))
for i in range(K):
    mask = labels == i
    plt.scatter(X[mask,0], X[mask,1], c=COLORS[i], label=NAMES[i], s=60, alpha=0.7)

plt.scatter(centers[:,0], centers[:,1], c='black', marker='X', s=180, zorder=5, label='Centroids')
plt.xlabel('Annual Income (k$)')
plt.ylabel('Spending Score (1-100)')
plt.title('Customer Segmentation — 5 Clusters')
plt.legend()
plt.tight_layout()
plt.savefig('customer_segments.png', dpi=120)
plt.show()
4

Profile each customer segment

Describe what makes each cluster distinct — this is the business insight.

profile = df.groupby('Cluster').agg({
    'Age':                        'mean',
    'Annual Income (k$)':         'mean',
    'Spending Score (1-100)':     'mean',
    'CustomerID':                 'count',
}).rename(columns={'CustomerID':'Count'}).round(1)

profile['Segment Name'] = NAMES
print(profile)
Age  Annual Income (k$)  Spending Score  Count Segment Name
Cluster
0       45.2                26.3            20.9     22      Careful
1       42.7                55.3            49.5     81     Standard
2       32.7                86.5            82.1     39       Target
3       25.3                87.8            17.6     20     Careless
4       40.0                26.3            79.4     38     Sensible
💡 Tip: "Target" customers (high income + high spending) are the most valuable segment for premium product marketing. "Careless" customers (high income + low spending) are an untapped opportunity — they have money but are not spending it here.

🎉 You Did It!

K-Means found five distinct customer personalities automatically, with no labelled data. This is unsupervised learning — the algorithm discovers structure in the data without being told what to look for.

Found something wrong?

Spotted a bug, broken code, or something that doesn't look right? Tell us what's off and we'll fix it.