Understanding Clustering with K-Means
K-means groups observations using numerical similarity rather than known outcome labels. Each row represents an observation, such as a customer, and each selected column represents a feature, such as monthly visits or spending. You choose K, the number of clusters. The result describes patterns in those features; it does not discover objectively correct customer types or explain why customers behave differently.
Each cluster has a centroid: the coordinate-wise mean of its assigned observations. K-means starts with initial centroids, assigns every observation to its nearest centroid using Euclidean distance, and recalculates the means. These steps repeat until a stopping condition is met. A centroid need not correspond to an actual customer. It is a numerical summary, so interpreting it requires knowing the features and their units.
The optimization objective, called inertia, is the sum of squared distances from observations to their assigned centroids. Squaring makes distant observations contribute disproportionately, which explains sensitivity to outliers. Smaller inertia means tighter clusters for the same data representation, not necessarily more useful segments. Different starting centroids can produce different local solutions. Multiple initializations reduce this risk but do not guarantee the globally best partition.
Feature preparation defines what similarity means. Without scaling, spending measured in thousands can overwhelm visits measured in single digits. Standardization subtracts each feature's mean and divides by its standard deviation, making variation more comparable. However, this is a modeling choice, not a universal rule: it can amplify low-variation noise. Correlated features can also count similar information repeatedly. Choose features and weights according to the analytical question, not merely availability.
K-means works best when compact, roughly spherical groups are meaningful in the chosen feature space. Elongated, unequal-density, or irregular groups may be poorly represented. It assigns every observation, including unusual cases, to a cluster. Cluster IDs are arbitrary identifiers, not rankings. Selecting K therefore requires both numerical checks and interpretation: inspect cluster sizes, feature distributions, stability, and whether the distinctions answer the original question. A useful segmentation is a defensible summary of the available data, not evidence that membership causes an outcome. Naming clusters should follow inspection rather than substitute for it.
Practical walkthrough
First, define the observation and time window. For customer segmentation, use one row per customer over the same period. Check missing values, impossible measurements, duplicates, and extreme values. Exclude identifiers: a customer number is not a meaningful distance feature. If missing values require imputation, document the rule and its consequences.
Second, decide whether you are describing an existing dataset or evaluating assignments for future observations. For future use, separate training and held-out data before learning preprocessing. Fit imputers, scalers, and K-means on training data only; transform held-out rows with those fitted objects. A scikit-learn Pipeline helps keep these operations together. Use validation data for choices and leave the final test set untouched until evaluation.
Third, compare a small, defensible range of K values. For ordinary randomized initialization, set an explicit n_init such as 10 and a random_state for reproducibility. Tabulate inertia and look for diminishing improvements: this is the elbow idea, and a clear elbow may not exist. Silhouette scores compare within-cluster closeness with separation from other clusters, but also favor some geometries. Neither measure establishes business usefulness.
Finally, profile each cluster using counts, medians, ranges, and original-unit summaries. Pandas grouping and aggregation support this inspection. Compare solutions across initializations or resampled training data, allowing for arbitrary label permutations. In the example below, fixed starting centroids make the calculation transparent. Equal weighting of two visit-count features is intentional, so scaling is omitted. The new observations demonstrate assignment only; they are not evidence of generalization quality. Real deployment requires broader checks over time.
Worked example
import numpy as np
from sklearn.cluster import KMeans
# Rows: customers; columns: weekly visits through channels A and B.
X_train = np.array([
[1, 1], [1, 3], [3, 1], [3, 3],
[7, 7], [7, 9], [9, 7], [9, 9]
], dtype=float)
# One explicit initialization, not one randomly chosen attempt.
model = KMeans(
n_clusters=2,
init=np.array([[1, 1], [9, 9]], dtype=float),
n_init=1,
algorithm="lloyd",
random_state=0
).fit(X_train)
# Canonical display IDs: order centroids by channel A visits.
order = np.argsort(model.cluster_centers_[:, 0])
display_id = np.empty(2, dtype=int)
display_id[order] = np.arange(2)
print("Labels:", display_id[model.labels_].tolist())
print("Centroids:", model.cluster_centers_[order].round(2).tolist())
print(f"Inertia: {model.inertia_:.2f}")
X_new = np.array([[2, 3], [8, 7]], dtype=float)
print("New assignments:", display_id[model.predict(X_new)].tolist())
Expected output
Labels: [0, 0, 0, 0, 1, 1, 1, 1]
Centroids: [[2.0, 2.0], [8.0, 8.0]]
Inertia: 16.00
New assignments: [0, 1]
Run this example with NumPy and scikit-learn installed; no external data is needed. The first four customers average two visits per channel, while the remaining four average eight. Each training customer differs from its centroid by one visit in each coordinate, contributing 1² + 1² = 2 to inertia. Eight contributions give 16.00. Display IDs are ordered for readability, not importance. The new customers are assigned without updating centroids. Fixed initialization justifies n_init=1 here, but does not replace multiple starts in ordinary exploration. These deliberately separated observations illustrate arithmetic, not evidence that real customers naturally form two distinct populations.
Common mistakes and how to avoid them
Choosing the K with the smallest training inertia.
More centroids can reduce inertia simply by adding flexibility. Compare diminishing improvements, separation, stability, cluster sizes, and practical interpretability instead.
Scaling the complete dataset before holding observations out.
Split first. Learn scaling and imputation from training rows only, then reuse those transformations unchanged for validation, test, and future rows.
Treating cluster numbers as ordered customer scores.
Profile the underlying observations before naming groups. Compare centroids or memberships across fits, because identical partitions can receive different numeric IDs.
Automatically deleting every unusual observation.
Investigate whether extremes are errors or valid behavior. Document any filtering and check sensitivity; removing valid extremes changes the population being summarized.
Review questions
Why is a centroid an average rather than necessarily an observed row?
For a fixed cluster membership, the coordinate-wise mean minimizes the sum of squared distances. Combining these means can produce a feature combination that no individual observation actually has.
Does low inertia establish that meaningful groups exist?
No. Inertia measures compactness in the chosen feature space. Even a continuous cloud can be partitioned into compact pieces, so interpretation, stability, and the analytical purpose remain essential.
What changes when spending is converted from dollars to cents without scaling?
Spending differences become 100 times larger, and their squared-distance contributions become 10,000 times larger. This can change assignments even though the underlying customer behavior has not changed.
How should an existing model handle a new customer?
Apply the fitted preprocessing, then assign the transformed row to its nearest fitted centroid using predict. This does not retrain the model, and even a very distant customer still receives an assignment.