hierarchical clustering on correlations in Python scipy/numpy?
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Introduction
Hierarchical clustering is useful when you want to group variables that behave similarly without choosing the number of groups in advance. When the input is a correlation matrix, the key step is converting correlation into a distance measure that SciPy can cluster correctly.
Correlation Is Similarity, Not Distance
A correlation coefficient tells you how strongly two variables move together. Clustering algorithms in scipy.cluster.hierarchy expect distances, where smaller values mean more similar observations.
A common conversion is distance = 1 - correlation. That works well when strong positive correlation should mean closeness. If negative correlation should also count as strong similarity, use distance = 1 - abs(correlation) instead.
The choice depends on the question:
- use
1 - correlationwhen positive and negative relationships should stay separate - use
1 - abs(correlation)when both directions represent strong association
Build The Correlation Matrix
Assume the columns of a DataFrame are the variables you want to cluster.
This gives you a square matrix where rows and columns represent the same variable set. SciPy does not want that full square matrix in linkage. It wants either raw observations or a condensed distance vector.
Convert To A Condensed Distance Vector
The usual workflow is:
- compute the correlation matrix
- transform it into a distance matrix
- convert that square matrix into condensed form with
squareform - call
linkage
The call to squareform is important. Passing the square distance matrix directly to linkage often leads to wrong results because SciPy may interpret it as observations rather than pairwise distances.
Choosing The Linkage Method
The method argument changes how cluster distances are updated:
- '
singleuses the closest pair between clusters' - '
completeuses the farthest pair' - '
averageuses the mean pairwise distance' - '
wardis popular, but it assumes Euclidean geometry and is usually not the right default for correlation-derived distances'
For correlation clustering, average is a sensible starting point because it is stable and easy to explain.
Cluster Rows Instead Of Columns
Sometimes you want to cluster observations, not variables. In that case, correlate rows by transposing first.
This pattern is useful in gene expression, user behavior analysis, and any setting where each row is an entity with multiple measured features.
Interpret The Dendrogram Carefully
A dendrogram shows merge order and merge distance. It does not automatically tell you the correct number of clusters. You still need domain judgment or a cutoff rule.
If two variables merge very low in the tree, they are strongly related under your chosen distance definition. If a variable joins the tree much higher up, it behaves differently from the rest.
Common Pitfalls
The most common mistake is feeding linkage a correlation matrix directly. A correlation matrix is neither raw observations nor a valid condensed distance vector, so the result is easy to misread.
Another mistake is forgetting that negative correlation may be either similarity or dissimilarity depending on the problem. The difference between 1 - correlation and 1 - abs(correlation) changes the cluster structure substantially.
A final issue is using ward with a non-Euclidean distance transformation. That combination is mathematically inconsistent for many correlation-based workflows and can produce misleading structure.
Summary
- Compute a correlation matrix first, then convert it to distance.
- Use
squareformbefore passing pairwise distances tolinkage. - Choose between
1 - correlationand1 - abs(correlation)based on what similarity means in your problem. - '
averagelinkage is usually a safer default thanwardfor correlation clustering.' - Read the dendrogram as a hierarchy, not as an automatic cluster count.
Related reading
- hierarchical clustering with gene expression matrix in python
- High AUC but bad predictions with imbalanced data
- High bias convolutional neural network not improving with more layers/filters
- High volume SVM machine learning system
- How are iloc and loc different?
- How are iloc and loc different?
- High performance fuzzy string comparison in Python, use Levenshtein or difflib
- Hopcroft–Karp algorithm in Python
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.