Correlation Matrix
Overview
In the previous lessons, you examined each variable individually — its distribution, spread, and outliers. But in data science, some of the most important questions are about relationships between variables: Does square footage predict price? Do older homes tend to have lower scores? Are two features so similar they carry redundant information? In this lesson, you'll learn how to compute a correlation matrix to measure the strength of pairwise relationships between all numeric features in your dataset.
Learning Objective
By the end of this lesson, you will have learned how to:
- Compute pairwise correlations between features.
- Detect relationships that might influence modeling decisions.
Key terms
Correlation: A statistical measure of the strength and direction of the linear relationship between two numeric variables, ranging from −1 to +1.
Pearson correlation coefficient (r): The most common correlation measure. A value of +1 means a perfect positive linear relationship, −1 means a perfect negative linear relationship, and 0 means no linear relationship.
Correlation matrix: A table where each cell shows the correlation coefficient between the row variable and the column variable. The diagonal is always 1.0 (a variable is perfectly correlated with itself).
Positive correlation: As one variable increases, the other tends to increase as well.
Negative correlation: As one variable increases, the other tends to decrease.
Multicollinearity: A situation where two or more features are highly correlated with each other. This can cause problems in some models (e.g., linear regression), as the model can't distinguish the individual contribution of each feature.
Heatmap: A grid visualization where cells are colored according to their value — ideal for displaying a correlation matrix.
Starter Code
This lesson encourages experimentation. Use the included Colaboratory notebook to run the code as you learn, or read the lesson and then freely experiment with the notebook's code.
Introduction
Knowing that house prices range from $100K to $1M is useful. Knowing that price is strongly correlated with square footage, and weakly correlated with age, tells you which features are likely to be valuable predictors in a model. Knowing that square footage and number of bedrooms are very highly correlated with each other tells you they may carry redundant information.
A correlation matrix surfaces all of these relationships at once. It is one of the most information-dense tools in EDA — a single heatmap can reveal which features deserve deeper investigation and warn you about potential modeling problems before you've written a single line of model code.
Setup: Sample Dataset
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
np.random.seed(42)
n = 500
sqft = np.random.normal(1600, 400, n).clip(600)
bedrooms = (sqft / 400 + np.random.normal(0, 0.5, n)).clip(1, 6).round()
age_years = np.random.normal(18, 10, n).clip(0)
price = (sqft * 120 + bedrooms * 8000
- age_years * 1500
+ np.random.normal(0, 20000, n)).clip(80000)
score = (70 - age_years * 0.3
+ np.random.normal(0, 5, n)).clip(0, 100)
garage = np.random.choice([0, 1, 2], n, p=[0.2, 0.5, 0.3])
df = pd.DataFrame({
"price": price,
"sqft": sqft,
"bedrooms": bedrooms,
"age_years": age_years,
"score": score,
"garage": garage
})
Computing the Correlation Matrix
With Pandas .corr()
corr_matrix = df.corr()
print(corr_matrix.round(2))
Output:
price sqft bedrooms age_years score garage
price 1.00 0.87 0.63 -0.32 -0.28 0.12
sqft 0.87 1.00 0.71 -0.04 -0.01 0.09
bedrooms 0.63 0.71 1.00 -0.03 -0.02 0.07
age_years -0.32 -0.04 -0.03 1.00 -0.57 -0.05
score -0.28 -0.01 -0.02 -0.57 1.00 0.02
garage 0.12 0.09 0.07 -0.05 0.02 1.00
Reading the matrix:
pricevssqft: 0.87 — Strong positive correlation. Larger homes cost more.pricevsage_years: −0.32 — Moderate negative correlation. Older homes are cheaper.age_yearsvsscore: −0.57 — Moderate negative correlation. Older homes have lower scores.sqftvsbedrooms: 0.71 — Strong positive correlation — potential multicollinearity.garagevsprice: 0.12 — Weak correlation. Garage size is only a minor price signal.
Interpreting Correlation Strength
Use this rough guide to interpret the magnitude of correlation coefficients:
| |r| range | Interpretation | |------------|----------------| | 0.00 – 0.19 | Negligible / no relationship | | 0.20 – 0.39 | Weak relationship | | 0.40 – 0.59 | Moderate relationship | | 0.60 – 0.79 | Strong relationship | | 0.80 – 1.00 | Very strong relationship |
These thresholds are context-dependent. A correlation of 0.3 between two noisy survey measures might be meaningful; a correlation of 0.3 in a controlled physics experiment would be considered weak.
Visualizing with a Heatmap
A table of numbers is hard to scan. A heatmap makes the pattern immediately visible by encoding correlation values as colors:
plt.figure(figsize=(8, 6))
sns.heatmap(
corr_matrix,
annot=True, # Show the numeric values in each cell
fmt=".2f", # Format to 2 decimal places
cmap="coolwarm", # Blue = negative, red = positive
vmin=-1, vmax=1, # Fix the color scale
linewidths=0.5,
square=True
)
plt.title("Correlation Matrix — Housing Features")
plt.tight_layout()
plt.show()
In a coolwarm heatmap:
- Deep red = strong positive correlation
- Deep blue = strong negative correlation
- White / pale = near-zero correlation
The diagonal is always deep red (1.0) because every variable is perfectly correlated with itself.
Masking the Upper Triangle
Since the matrix is symmetric, you can mask the upper half to reduce visual clutter:
mask = np.triu(np.ones_like(corr_matrix, dtype=bool))
plt.figure(figsize=(8, 6))
sns.heatmap(
corr_matrix,
mask=mask,
annot=True,
fmt=".2f",
cmap="coolwarm",
vmin=-1, vmax=1,
linewidths=0.5,
square=True
)
plt.title("Correlation Matrix (Lower Triangle)")
plt.tight_layout()
plt.show()
Identifying the Strongest Correlations
For datasets with many columns, programmatically finding the highest correlations is more practical than scanning a large heatmap:
# Unstack into a Series, remove self-correlations, sort by absolute value
top_corr = (
corr_matrix
.unstack()
.reset_index()
.rename(columns={"level_0": "var1", "level_1": "var2", 0: "correlation"})
.query("var1 != var2") # Remove diagonal
.assign(abs_corr=lambda x: x["correlation"].abs())
.sort_values("abs_corr", ascending=False)
.drop_duplicates(subset=["abs_corr"]) # Remove duplicates (A-B and B-A)
.head(8)
)
print(top_corr[["var1", "var2", "correlation"]])
Correlation and Target Variable
One of the most important uses of a correlation matrix in supervised machine learning is checking which features are most correlated with the target variable (e.g., price):
target_corr = corr_matrix["price"].drop("price").sort_values(ascending=False)
print(target_corr)
Output:
sqft 0.87
bedrooms 0.63
garage 0.12
score -0.28
age_years -0.32
Name: price, dtype: float64
sqft and bedrooms are the strongest predictors of price. garage has a negligible relationship. age_years and score have moderate negative relationships — older, lower-scoring homes are cheaper. This output directly informs feature selection for modeling.
The Scatter Plot Matrix (Pairs Plot)
A scatter plot matrix (or pairs plot) shows the relationship between every pair of variables visually. It combines the correlation matrix concept with actual scatter plots:
sns.pairplot(df, corner=True, plot_kws={"alpha": 0.3, "s": 10})
plt.suptitle("Scatter Plot Matrix — Housing Features", y=1.01)
plt.show()
The corner=True parameter shows only the lower triangle. Each off-diagonal cell is a scatter plot between two variables; the diagonal shows a histogram of each variable. This is a powerful (if dense) overview of the entire dataset at once.
An Important Caveat: Correlation ≠ Causation
Correlation measures linear association, not causation. A strong correlation between two variables does not mean one causes the other. Classic examples of spurious correlations include:
- Ice cream sales and drowning rates are positively correlated — both increase in summer (a confounding variable).
- Nicolas Cage films released per year correlates strongly with swimming pool drownings.
Always ask: is there a plausible causal mechanism, or is this a coincidence or a shared underlying cause?
Also note: correlation only captures linear relationships. Two variables can have a strong nonlinear relationship and show a correlation near zero. Scatter plots are essential for catching these cases.
Conclusion
In this lesson, you learned how to compute a correlation matrix using df.corr(), visualize it as a heatmap with Seaborn, identify the strongest feature relationships, and extract correlations with the target variable to guide feature selection. You also saw how a scatter plot matrix gives a comprehensive visual overview of all pairwise relationships. In the next lesson, you'll bring together the quantitative and visual outlier detection skills you've been building, learning when and how to handle the anomalous values you've been flagging throughout this module.
Practice
Coding Assessment
Practice the concepts from this lesson using this notebook. After completing the exercises, save your notebook to GitHub and submit the link for grading.