
STAT 204 – Introduction to Statistical Data Analysis
18 Nov 2025
Raw data:

With clusters identified:

The algorithm discovers natural groupings in the data!
Supervised Learning (Classification)
Unsupervised Learning (Clustering)
Note: Clustering can be used to create features for supervised learning!
Pattern detection: - Identify natural groupings in your data - Market segmentation (customer types) - Image segmentation - Document organization
Feature creation: - Create new categorical variables based on clusters - Use cluster membership as a predictor in other models
Data exploration: - Better understand the structure of your data - Generate hypotheses for further investigation
⚠️ Warning: Can also result in noise if patterns don’t really exist!
Given two observations \(\mathbf{x}_i\) and \(\mathbf{x}_{i'}\), a dissimilarity measure \(d_{ii'}\) must satisfy:
We typically construct the proximity matrix \(\mathbf{D}\), an \(n \times n\) matrix where element \((i, i')\) is \(d_{ii'}\)
Euclidean distance (most common): \(d_{ii'} = \sqrt{\sum_{j=1}^p (x_{ij} - x_{i'j})^2}\)
Minkowski metric (generalization): \[d_{ii'} = \left(\sum_{j=1}^p |x_{ij} - x_{i'j}|^\lambda\right)^{1/\lambda}\]
where \(\lambda = 2\) gives Euclidean distance, \(\lambda = 1\) gives Manhattan distance
Important!
Make sure to scale your variables if they’re on different units/scales!
K-means tries to minimize the within-cluster sum of squares:
\[\text{minimize} \sum_{k=1}^K \sum_{C(i)=k} \sum_{C(i')=k} d(\mathbf{x}_i, \mathbf{x}_{i'})\]
In words: minimize the sum over all clusters of the total distances between points within each cluster
With Euclidean distance, this is equivalent to minimizing: \[\sum_{k=1}^K \sum_{C(i)=k} \|\mathbf{x}_i - \bar{\mathbf{x}}_k\|^2\]
where \(\bar{\mathbf{x}}_k\) is the centroid (mean) of cluster \(k\)
Algorithm
Initialize: Randomly assign each observation to one of K clusters
Iterate until convergence:
For each cluster \(k\), compute the cluster centroid \(\bar{\mathbf{x}}_k\) (the vector of column means)
Assign each observation to the cluster with the closest centroid
The algorithm converges when cluster assignments stop changing
Note
Convergence: The algorithm is guaranteed to converge, but not necessarily to the global optimum — only to a local minimum!
Initial random assignment:

After reassignment:

⭐ Stars show cluster centroids



Solution: Run the algorithm multiple times with different random starts and pick the best solution!
Fertility Agriculture Examination Education Catholic
Courtelary 80.2 17.0 15 12 9.96
Delemont 83.1 45.1 6 9 84.84
Franches-Mnt 92.5 39.7 5 5 93.40
Infant.Mortality
Courtelary 22.2
Delemont 22.2
Franches-Mnt 20.2
Fertility Agriculture Examination Education Catholic Infant.Mortality
1 58.30909 19.50909 25.72727 23.000 22.21455 19.22727
2 68.32500 55.90500 17.05000 7.850 7.55000 19.67000
3 80.55000 65.51875 9.43750 6.625 96.15000 20.77500
Interpretation
Add your interpretations on Ed Discussion
library(ggplot2)
# Project onto first 2 principal components for visualization
pc_swiss <- prcomp(swiss)
plotDF <- data.frame(
PC1 = pc_swiss$x[,1],
PC2 = pc_swiss$x[,2],
Cluster = factor(kmeans_swiss$cluster)
)
ggplot(plotDF, aes(x=PC1, y=PC2, color=Cluster)) +
geom_point(size=3) +
theme_minimal() +
labs(title="Swiss Data: K-means with K=3")The penguins dataset has known species labels — let’s see if K-means can recover them!
library(dplyr)
library(palmerpenguins)
# Prepare data: select variables and remove missing values
penguins_clean <- penguins %>%
dplyr::select(bill_length_mm, bill_depth_mm,
flipper_length_mm, body_mass_g, sex, species) %>%
na.omit()
# Standardize the numeric variables
penguins_scaled <- penguins_clean %>%
mutate(across(c(bill_length_mm, bill_depth_mm,
flipper_length_mm, body_mass_g), scale))
# Convert sex to numeric (0/1) for clustering
penguins_for_clustering <- penguins_scaled %>%
mutate(sex_numeric = as.numeric(sex) - 1) %>%
select(bill_length_mm, bill_depth_mm, flipper_length_mm,
body_mass_g, sex_numeric)
# Run K-means with K=3 (there are 3 penguin species)
set.seed(1)
km_penguins <- kmeans(penguins_for_clustering, centers=3, nstart=10)
# Compare clusters to true species
table(Cluster = km_penguins$cluster, Species = penguins_clean$species) Species
Cluster Adelie Chinstrap Gentoo
1 25 61 0
2 0 0 119
3 121 7 0
Not perfect, but pretty good! Clusters 2 and 3 mostly separate Gentoo and Adelie.
How do we choose K? Try multiple values and look for an “elbow” in the plot:
Look for where the decrease starts to level off — here maybe K=3 or K=4?
Limitation 1: Must specify K
You need to decide on the number of clusters beforehand (though the elbow method can help)
Limitation 2: Assumes spherical clusters
K-means works best when clusters are roughly circular/spherical — it can fail on complex shapes
Limitation 3: Sensitive to outliers
Centroids can be pulled by extreme values
Limitation 4: Scale matters
Variables with larger scales dominate — always standardize!
K-means struggles with non-convex shapes! Other methods (e.g., DBSCAN) work better here.

Key features:
Algorithm
Start with \(n\) clusters (each observation is its own cluster)
Repeat until only one cluster remains:
Compute all pairwise inter-cluster dissimilarities
Identify the two clusters that are most similar
Merge these two clusters
Record the height (dissimilarity) at which the merge occurs
The result is a dendrogram!
How do we measure dissimilarity between clusters? Different linkage methods:
Maximum dissimilarity between any two points in the clusters
\[d_{\text{complete}}(A, B) = \max_{i \in A, i' \in B} d_{ii'}\]
Most popular; tends to produce compact clusters
Minimum dissimilarity between any two points in the clusters
\[d_{\text{single}}(A, B) = \min_{i \in A, i' \in B} d_{ii'}\]
Can produce “chaining” (long, stretched clusters)
Mean of all pairwise dissimilarities
\[d_{\text{average}}(A, B) = \frac{1}{|A||B|}\sum_{i \in A}\sum_{i' \in B} d_{ii'}\]
Compromise between single and complete
Dissimilarity between cluster centroids
Can sometimes lead to inversions (not monotonic)
Different linkage methods can give very different tree structures!
body brain
Arctic fox 3.385 44.5
Owl monkey 0.480 15.5
Mountain beaver 1.350 8.1
Use cutree() to cut the dendrogram at different heights or to get K clusters:
Complete linkage:
Average linkage:
Tree structures can look quite different!
European countries grouped by protein consumption patterns:
| Feature | K-means | Hierarchical |
|---|---|---|
| Choose K? | ✅ Yes, upfront | ❌ No, choose later from dendrogram |
| Computational | ✅ Fast, scalable | ⚠️ Slower for large data |
| Deterministic? | ❌ No, random starts | ✅ Yes (given distance) |
| Visual | Scatter plot | Dendrogram tree |
| Cluster shapes | Spherical/convex | More flexible |
Recommendation
Try both methods and compare results! They often give complementary insights.
Problem: Variables on different scales dominate the clustering
# A tibble: 2 × 6
bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sex species
<dbl> <dbl> <int> <int> <fct> <fct>
1 39.1 18.7 181 3750 male Adelie
2 39.5 17.4 186 3800 female Adelie
# A tibble: 2 × 6
bill_length_mm[,1] bill_depth_mm[,1] flipper_length_mm[,1] body_mass_g[,1]
<dbl> <dbl> <dbl> <dbl>
1 -0.895 0.780 -1.42 -0.568
2 -0.822 0.119 -1.07 -0.506
# ℹ 2 more variables: sex <fct>, species <fct>
Always standardize unless you have a good reason not to!
Clustering algorithms typically can’t handle missing data directly.
Options:
Important Question
How do we know if our clusters are “real” or just artifacts?
Approaches:
Silhouette analysis: Measures how similar each point is to its own cluster vs other clusters
Gap statistic: Compares within-cluster variation to a null reference distribution
Domain knowledge: Do the clusters make sense? Can you interpret them?
Stability: Do you get similar results with different random samples?
Warning
Clustering can find patterns in random data! Always be skeptical and validate.
Problem: In high dimensions, all distances become similar!
Solutions: Dimension reduction (PCA) before clustering, or use algorithms designed for high dimensions
Can K-means separate handwritten 0s and 1s?
True_Label
Cluster 0 1
1 10 1135
2 970 0
Almost perfect separation! (Without using any labels during training)
Often works well to:
Benefits: Faster, more stable, avoids curse of dimensionality
Beyond K-means and hierarchical:
Each method has strengths and weaknesses — choose based on your data and goals!
What We Learned
✅ Clustering is unsupervised learning — finding groups without labels
✅ K-means: Fast, but requires choosing K and assumes spherical clusters
✅ Hierarchical: Flexible, creates dendrogram, linkage method matters
✅ Distance matters: Scale your variables, choose appropriate metric
✅ Validation is crucial: Don’t trust clusters blindly!
✅ Real-world tips: - Try multiple methods and compare - Use domain knowledge to interpret results - Consider dimension reduction first for high-dimensional data
Books:
R Packages:
stats: kmeans(), hclust(), cutree()cluster: More advanced methods. See R Packagefactoextra: Visualization tools. See R PackageOnline:
Try These:
Load the USArrests dataset and perform K-means clustering with K=3. Interpret the clusters.
Use hierarchical clustering on the same data with different linkage methods. How do results differ?
Apply the elbow method to determine the optimal number of clusters.
Create a dendrogram and color different branches based on cluster membership.
Compare clustering results on raw vs. scaled data. What changes?
Thank you!
![]()
STAT 204 – Intro to Statistical Data Analysis