Skip to main content

PCA from the covariance matrix

Principal component analysis finds the directions in which a cloud of data spreads most. Centre the data, form the covariance matrix, and its eigenvectors are those directions; derive why, and why the same line makes the perpendicular gaps as small as possible.
M03.6.3L2 Intermediate25 min
In review (what this means)

The maths and code on this page are checked by automated tests on every change, but an independent reader has not signed it off yet. Spot a mistake or a confusing step? Tell us.

Before this lesson: M03.6.2 Image compression by rank M03.3.4 The Rayleigh quotient and the extreme directions M06.10.2 Rules of covariance and the variance of a sum

What you will be able to do
  • Centre a data matrix and form its covariance matrix C = X_c-transpose X_c / (n - 1).
  • Derive that the variance of the data along a unit direction u is u-transpose C u, and that its largest value is the top eigenvalue, reached along the top eigenvector.
  • Compute the principal directions, their variances and the explained-variance ratios of a small data set by hand and with numpy.linalg.eigh.
  • Prove with Pythagoras that the direction of largest variance is also the line through the mean with the smallest sum of squared perpendicular gaps.

The question

A data set with fifty measurements per item cannot be drawn: we see in two dimensions, three at a push. Before clustering it, plotting it or feeding it to a model, we would like to know which directions in that fifty-dimensional space the data actually uses. Which single direction shows the most of a cloud of points, and how do we find it?

From the last lesson

1. How many numbers does it take to store \(k\) layers of an \(m \times n\) picture?

Show answer

\(k(m + n + 1)\), against \(mn\) for the picture itself.

2. A truncation keeps 99% of the energy. What is its relative error?

Show answer

The square root of the share dropped: \(\sqrt{0.01} = 10\%\).

Intuition

Take the running four points \((0, 1)\), \((3, 2)\), \((4, 4)\) and \((7, 5)\). Draw a line through their mean and drop each point straight onto it, at a right angle. The dropped points, the shadows, are spread out along the line. Turn the line, and the spread of the shadows changes.

A plot of four blue data points at (0, 1), (3, 2), (4, 4) and (7, 5), and a black cross at their mean (3.5, 3). A wide pale orange line through the mean rises with slope 0.618, labelled first principal direction. Two orange arrows from the mean, q 1 along the line and q 2 at a right angle to it. From each blue point a short purple segment meets the line at a right angle, ending in a small vermillion dot. Pointers label a data point, its shadow on the line, a perpendicular gap, and the mean. The title reads: spread along the line is as large as it can be; the gaps as small.
M03.6.3-F1

The first principal direction of the four points. Along this line the shadows (vermillion) spread out the most, and the perpendicular gaps (purple) are the smallest.

The direction in which the shadows spread most is the first principal direction. It is the one direction that keeps the most of what distinguishes the points from one another. Principal component analysis, PCA, finds it, then the best direction perpendicular to it, and so on. The same line also hugs the points as closely as possible, measured at right angles; that is the promise made in the pitfalls of M02.10.4.

Build it up

Step 1. Centre. Subtract the mean from every point. The mean of the four points is \((3.5, 3)\), and the centred points are the rows of

\[ \mat{X}_c = \begin{bmatrix} -3.5 & -2 \\ -0.5 & -1 \\ 0.5 & 1 \\ 3.5 & 2 \end{bmatrix} . \]

Each column of \(\mat{X}_c\) now adds up to zero. Spread is measured from the centre of the cloud, so this is the right place to stand.

Step 2. The shadow of one point. For a unit vector \(\vect{u}\) and a centred point \(\vect{x}_i\), the shadow is \({(\vect{u} \cdot \vect{x}_i)\,\vect{u}}\), and its signed position along the line is the number \(\vect{u} \cdot \vect{x}_i\), called the score of the point. The four scores are the entries of \(\mat{X}_c\vect{u}\). They add up to zero, because each column of \(\mat{X}_c\) does.

Step 3. The variance of the scores. Their mean is zero, so their sample variance is the sum of their squares divided by \(n - 1\):

\[ \begin{aligned} \frac{1}{n-1}\sum_i (\vect{u} \cdot \vect{x}_i)^2 &= \frac{1}{n-1}\,\norm{\mat{X}_c\vect{u}}^2 \\ &= \vect{u}\T\,\frac{\mat{X}_c\T\mat{X}_c}{n-1}\,\vect{u} \\ &= \vect{u}\T\mat{C}\,\vect{u} . \end{aligned} \]

The middle step writes the squared length as \({(\mat{X}_c\vect{u})\T(\mat{X}_c\vect{u})}\) and uses \({(\mat{X}_c\vect{u})\T} = {\vect{u}\T\mat{X}_c\T}\). The matrix \(\mat{C} = {\mat{X}_c\T\mat{X}_c/(n - 1)}\) is the covariance matrix of the data (M06.10.2): its diagonal holds the variances of the features, and off the diagonal sit their covariances.

Step 4. Turn the direction. With \(\vect{u} = {(\cos\theta, \sin\theta)}\), the variance \(\vect{u}\T\mat{C}\vect{u}\) is a smooth function of the angle. Plot it and read off the best angle.

A green curve of the variance u transpose C u against the angle of the direction u, from 0 to 180 degrees. It starts at 8.33 at 0 degrees, labelled along the x-axis: 25 over 3, about 8.33, rises to a maximum of 11.42 at 31.7 degrees, marked with an orange dot and a dashed line, labelled largest: lambda 1 equals 11.42 at 31.7 degrees, along q 1, falls to a minimum of 0.24 at 121.7 degrees, labelled smallest: lambda 2 equals 0.24, and rises again to 8.33 at 180 degrees.
M03.6.3-F2

The variance of the four points seen along each direction. The highest and lowest points of the curve are exactly the two eigenvalues of \(\mat{C}\), and they sit \(90°\) apart.

The formal statement

Result 1: the direction of largest variance. Let \(\mat{C}\) have eigenvalues \(\lambda_1 \ge \lambda_2 \ge \cdots \ge \lambda_d\) and orthonormal eigenvectors \(\vect{q}_1, \dots, \vect{q}_d\), as the spectral theorem promises for a symmetric matrix (M03.3.2). Then over all unit vectors \(\vect{u}\), the variance \(\vect{u}\T\mat{C}\vect{u}\) is largest, equal to \(\cparam{\lambda_1}\), at \(\vect{u} = \cparam{\vect{q}_1}\).

Why. This is the Rayleigh quotient of M03.3.4. Write \(\vect{u}\) in the eigenbasis, \(\vect{u} = {c_1\vect{q}_1 + \cdots + c_d\vect{q}_d}\), with \({c_1^2 + \cdots + c_d^2} = 1\) because \(\vect{u}\) is a unit vector. Then \(\mat{C}\vect{u} = \sum_i c_i\lambda_i\vect{q}_i\) and

\[ \begin{aligned} \vect{u}\T\mat{C}\,\vect{u} &= \lambda_1 c_1^2 + \cdots + \lambda_d c_d^2 \\ &\le \lambda_1\,(c_1^2 + \cdots + c_d^2) = \lambda_1 , \end{aligned} \]

with equality when \(c_1 = \pm 1\) and the rest are zero, that is at \(\vect{u} = \pm\vect{q}_1\).

Result 2: the later directions. Among unit vectors perpendicular to \(\vect{q}_1\), so with \(c_1 = 0\), the same line of algebra gives at most \(\lambda_2\), reached at \(\vect{q}_2\). Going on, the \(j\)-th principal direction is \(\vect{q}_j\), perpendicular to all the earlier ones, and the variance along it is \(\lambda_j\).

Result 3: explained variance. The total variance is the sum of the variances of the features, the trace of \(\mat{C}\), which equals the sum of its eigenvalues (M03.1.3). So the directions share it out exactly, and the explained-variance ratio of direction \(j\) is

\[ \frac{\lambda_j}{\operatorname{tr}(\mat{C})} = \frac{\lambda_j}{\lambda_1 + \cdots + \lambda_d} . \]

Result 4: largest spread, smallest gaps. For a centred point \(\vect{x}_i\) and a unit \(\vect{u}\), the shadow and the perpendicular gap \(d_i\) are the two sides of a right-angled triangle whose long side is \(\vect{x}_i\).

A right-angled triangle. A blue arrow x i runs from the mean, marked with a cross, up to a point. A pale orange line through the mean carries a short orange arrow u and a vermillion arrow, the shadow (u dot x i) u. A purple segment d i drops from the tip of x i to the tip of the shadow, meeting the line at a marked right angle. Beside it: the squared length of x i equals (u dot x i) squared plus d i squared. Add over all points: fixed equals spread along u plus gaps. Make one big and the other is small.
M03.6.3-F3

Pythagoras for one point. Its squared distance from the mean is fixed; turning the line only moves it between the shadow and the gap.

By Pythagoras, \({\norm{\vect{x}_i}^2} = {(\vect{u} \cdot \vect{x}_i)^2 + d_i^2}\). Add over the points and use Step 3:

\[ \sum_i \norm{\vect{x}_i}^2 = (n-1)\,\vect{u}\T\mat{C}\,\vect{u} + \closs{\sum_i d_i^2} . \]

The left side does not depend on \(\vect{u}\). So the \(\vect{u}\) that makes the variance largest makes the sum of squared perpendicular gaps smallest: the first principal direction is the best fitting line through the mean, measured at right angles. The smallest sum of gaps is \({(n - 1)}\) times the variance left over.

Go deeper: why the best line passes through the mean

Let a line pass through a point \(\vect{p}\) in the direction \(\vect{u}\), and let \(\mat{G}\) be the matrix that removes the part along \(\vect{u}\), so the gap of a data point \(\vect{y}_i\) is \({\mat{G}(\vect{y}_i - \vect{p})}\). Write \(\vect{m}\) for the mean and split \(\vect{y}_i - \vect{p} = {(\vect{y}_i - \vect{m}) + (\vect{m} - \vect{p})}\). Expanding the squares,

\[ \begin{aligned} &\sum_i \norm{\mat{G}(\vect{y}_i - \vect{p})}^2 \\ &\quad= \sum_i \norm{\mat{G}(\vect{y}_i - \vect{m})}^2 \\ &\qquad + n\,\norm{\mat{G}(\vect{m} - \vect{p})}^2 \\ &\qquad + 2\,\vect{g} \cdot \mat{G}\sum_i (\vect{y}_i - \vect{m}) , \end{aligned} \]

where \(\vect{g} = {\mat{G}(\vect{m} - \vect{p})}\). The last sum is zero, because the deviations from the mean add up to zero. The middle term is never negative and vanishes when the line passes through \(\vect{m}\). So for any direction, moving the line to pass through the mean can only shrink the gaps.

Worked example

The running four points, by hand. From \(\mat{X}_c\) above, the scatter matrix is

\[ \mat{X}_c\T\mat{X}_c = \begin{bmatrix} 25 & 15 \\ 15 & 10 \end{bmatrix} , \]

since \({12.25 + 0.25 + 0.25 + 12.25} = 25\), \({7 + 0.5 + 0.5 + 7} = 15\) and \({4 + 1 + 1 + 4} = 10\). With \(n - 1 = 3\), \(\mat{C}\) is a third of it. The scatter matrix is easier to work with; its eigenvectors are those of \(\mat{C}\) and its eigenvalues are three times as big.

Five boxes joined by green arrows. 1, Centre: subtract the mean (3.5, 3), giving (minus 3.5, minus 2), (minus 0.5, minus 1), (0.5, 1), (3.5, 2). 2, Scatter matrix: X c transpose X c has rows (25, 15) and (15, 10); C is a third of it. 3, Eigenvalues: lambda squared minus 35 lambda plus 25 equals 0, so lambda equals (35 plus or minus 15 root 5) over 2, about 34.27 and 0.73. 4, Direction: (25 minus 34.27) x plus 15 y equals 0, slope (root 5 minus 1) over 2, about 0.618. 5, highlighted in yellow, Variances: divide by n minus 1 equals 3: 11.42 and 0.24; share of the first 97.9 per cent.
M03.6.3-F4

From four points to their first principal direction, in five steps.

Eigenvalues. The characteristic polynomial is \(\lambda^2 - 35\lambda + {(250 - 225)} = \lambda^2 - 35\lambda + 25\). Since \(35^2 - 4 \cdot 25 = 1125 = 225 \cdot 5\), the roots are

\[ \lambda = \frac{35 \pm 15\sqrt5}{2} \approx 34.27 \text{ and } 0.73 . \]

Direction. The first row of the scatter matrix minus \(\lambda_1\) gives \({(25 - \lambda_1)\,x} + 15y = 0\), so the slope is

\[ \begin{aligned} \frac{y}{x} &= \frac{\lambda_1 - 25}{15} = \frac{15\sqrt5 - 15}{30} \\ &= \frac{\sqrt5 - 1}{2} \approx 0.618 . \end{aligned} \]

Variances. Dividing by 3, the variances along the two principal directions are about \(11.42\) and \(0.24\). The total variance is \({(25 + 10)/3} \approx 11.67\), the sum of the variances of \(x\) (\(8.33\)) and \(y\) (\(3.33\)). The first direction explains \({\lambda_1/(\lambda_1 + \lambda_2)} = \tfrac12 + \tfrac{3\sqrt5}{14} \approx 97.9\%\) of it.

The promise of M02.10.4. The least-squares line through these points has slope \(0.6\); the first principal direction has slope \(0.618\). Both pass through the mean, but they answer different questions.

Two plots of the four blue points. Left, titled Least squares (M02.10.4): a vermillion line of slope 0.6 with short purple vertical bars from each point to the line; the vertical gaps have squares adding to 1. Right, titled First principal direction: an orange line of slope 0.618 with purple segments meeting it at right angles; the perpendicular gaps have squares adding to 0.73.
M03.6.3-F6

Two best lines. Least squares makes the vertical gaps small; the first principal direction makes the perpendicular gaps small.

The perpendicular gaps of the principal line have squares adding to the smaller eigenvalue of the scatter matrix, \({(35 - 15\sqrt5)/2} \approx 0.729\), by Result 4. The least-squares line has smaller vertical gaps (1 against about 1.01) but larger perpendicular ones (about 0.735).

Code

From scratch: centre, form \(\mat{C}\), take its eigenvectors with numpy.linalg.eigh and sort them by size. eigh returns the eigenvalues in ascending order, so we reverse.

import numpy as np

def pca_eigh(X):
    """Principal directions (as columns), their variances and the explained-variance ratios."""
    X = np.asarray(X, dtype=float)
    Xc = X - X.mean(axis=0)
    C = Xc.T @ Xc / (len(X) - 1)
    variances, directions = np.linalg.eigh(C)      # ascending order
    order = np.argsort(variances)[::-1]
    variances, directions = variances[order], directions[:, order]
    return directions, variances, variances / variances.sum(), C

points = np.array([[0.0, 1.0], [3.0, 2.0], [4.0, 4.0], [7.0, 5.0]])
Q, lam, ratio, C = pca_eigh(points)
print("C =\n", C.round(4))
print("variances:", lam.round(4), "  ratios:", ratio.round(4))
print("slope of the first direction:", round(Q[1, 0] / Q[0, 0], 4))
C =
 [[8.3333 5.    ]
 [5.     3.3333]]
variances: [11.4235  0.2432]   ratios: [0.9792 0.0208]
slope of the first direction: 0.618

Now check Results 1 and 4 on many directions: the variance never beats \(\lambda_1\), and variance plus gaps is always the same total.

Xc = points - points.mean(axis=0)
angles = np.linspace(0, np.pi, 3601)
best, total_ok = -np.inf, True
for a in angles:
    u = np.array([np.cos(a), np.sin(a)])
    variance = u @ C @ u
    gaps = np.sum((Xc - np.outer(Xc @ u, u)) ** 2)            # squared perpendicular gaps
    total_ok &= np.isclose(3 * variance + gaps, np.sum(Xc ** 2))
    best = max(best, variance)
print("largest variance found:", round(best, 4), "  lambda_1:", round(lam[0], 4))
print("variance and gaps always add up to the same total:", total_ok)

u_ls = np.array([1.0, 0.6]) / np.hypot(1.0, 0.6)                # direction of the least-squares line
print("perpendicular gaps, principal line:", round(np.sum((Xc - np.outer(Xc @ Q[:, 0], Q[:, 0])) ** 2), 4),
      "  least-squares line:", round(np.sum((Xc - np.outer(Xc @ u_ls, u_ls)) ** 2), 4))
largest variance found: 11.4235   lambda_1: 11.4235
variance and gaps always add up to the same total: True
perpendicular gaps, principal line: 0.7295   least-squares line: 0.7353

The search over 3,601 directions never beats \(\lambda_1\), and comes within \(10^{-5}\) of it.

Explore

The module’s interactive, the rank slider, is in lesson M03.6.2. Its bars are the singular values of a picture; the next lesson shows that the variances of PCA are squared singular values too, divided by \(n - 1\), so the same picture of kept and dropped bars describes a PCA.

Pitfalls

Two plots of the four blue points. Left, marked with a cross and titled Not centred: a pale orange line through the origin, marked with a cross, with slope 0.784, labelled a line through the origin; it passes below and to the right of the cloud's direction. Right, marked with a tick and titled Centred first: a pale orange line through the mean, marked with a cross, with slope 0.618, running along the cloud.
M03.6.3-F5

Wrong beside right. Without centring, the top eigenvector of \({\mat{X}\T\mat{X}}\) describes where the cloud sits as seen from the origin, not how it spreads.

“I can skip centring; the eigenvectors will sort it out.”

Without centring, \(\vect{u}\T\mat{X}\T\mat{X}\vect{u}\) counts the distance of the points from the origin, not from their mean. For the four points, the top eigenvector of \(\mat{X}\T\mat{X} = \begin{bmatrix} 74 & 57 \\ 57 & 46 \end{bmatrix}\) has slope about \(0.784\), pulled towards the direction of the mean, \((3.5, 3)\), which has slope \(0.857\). The spread of the cloud has slope \(0.618\).

“The first principal direction is the regression line.”

Regression predicts \(y\) from \(x\), so it measures errors in \(y\) only, vertically. PCA treats the features alike and measures at right angles. On the four points the slopes are \(0.6\) and \(0.618\); on noisier data they can differ a lot. Use regression to predict a target, PCA to describe the shape of the data.

“Dividing by \(n\) instead of \(n - 1\) gives different components.”

M06.10 and some textbooks divide by \(n\). That multiplies every eigenvalue of \(\mat{C}\) by the same factor, so the directions and the explained-variance ratios do not change; only the variances themselves differ, by the factor \((n - 1)/n\).

Check yourself

Recall

1. Why must the data be centred before PCA?

Show answer

Variance is spread about the mean. Without centring, \(\vect{u}\T\mat{X}\T\mat{X}\vect{u}\) measures distances from the origin, and the top direction points towards the mean instead of along the spread.

2. What is the variance of the data along a unit direction \(\vect{u}\)?

Show answer

\(\vect{u}\T\mat{C}\vect{u}\), with \(\mat{C} = {\mat{X}_c\T\mat{X}_c/(n - 1)}\).

3. Which direction makes that variance largest, and what is the largest value?

Show answer

The eigenvector \(\vect{q}_1\) of \(\mat{C}\) for the largest eigenvalue, and the value is \(\lambda_1\).

4. What is the explained-variance ratio of the \(j\)-th principal direction?

Show answer

\({\lambda_j/\operatorname{tr}(\mat{C})}\), its eigenvalue divided by the sum of all the eigenvalues.

5. Why does the direction of largest variance also give the smallest perpendicular gaps?

Show answer

By Pythagoras, each point’s squared distance from the mean is its squared score plus its squared gap. The total of the squared distances is fixed, so making the scores spread most makes the gaps smallest.

Exercises

1. ★ Data have covariance matrix \(\mat{C} = \begin{bmatrix} 4 & 0 \\ 0 & 1 \end{bmatrix}\). What are the principal directions and the explained-variance ratios?

Show solution

\(\mat{C}\) is diagonal, so its eigenvectors are \((1, 0)\) and \((0, 1)\) with eigenvalues 4 and 1. The first principal direction is the \(x\)-axis, with ratio \(4/5 = 80\%\), and the second is the \(y\)-axis, with \(20\%\). When the features are uncorrelated, PCA simply ranks them by variance.

2. ★★ Find the principal directions, their variances and the sum of the squared perpendicular gaps to the first one, for the points \((2, 1)\), \((1, 2)\), \((-2, -1)\) and \((-1, -2)\).

Show solution

The mean is \((0, 0)\), so the points are already centred. The scatter matrix is

\[ \mat{X}_c\T\mat{X}_c = \begin{bmatrix} 10 & 8 \\ 8 & 10 \end{bmatrix} , \]

since \({4 + 1 + 4 + 1} = 10\) and \({2 + 2 + 2 + 2} = 8\). Its eigenvectors are \({(1, 1)/\sqrt2}\) with eigenvalue 18 and \({(1, -1)/\sqrt2}\) with eigenvalue 2. Dividing by \(n - 1 = 3\), the variances are 6 and \(2/3\), and the first direction explains \(18/20 = 90\%\). By Result 4 the squared perpendicular gaps to the line \(y = x\) add up to 2: each point is \(1/\sqrt2\) from it, and \({4 \times \tfrac12} = 2\).

3. ★★★ Show that projecting the centred data onto the span of the first \(k\) principal directions keeps a variance of \({\lambda_1 + \cdots + \lambda_k}\), that is \({\sum_i \norm{\text{projection of }\vect{x}_i}^2/(n - 1)} = {\lambda_1 + \cdots + \lambda_k}\).

Show solution

The directions \(\vect{q}_1, \dots, \vect{q}_k\) are orthonormal, so the projection of \(\vect{x}_i\) onto their span is \({\sum_{j \le k} (\vect{q}_j \cdot \vect{x}_i)\,\vect{q}_j}\), and its squared length is the sum of the squared coefficients, \({\sum_{j \le k} (\vect{q}_j \cdot \vect{x}_i)^2}\). Sum over the points, divide by \(n - 1\) and swap the two sums:

\[ \begin{aligned} &\frac{1}{n-1}\sum_i \sum_{j \le k} (\vect{q}_j \cdot \vect{x}_i)^2 \\ &\quad= \sum_{j \le k} \vect{q}_j\T\mat{C}\,\vect{q}_j \\ &\quad= \lambda_1 + \cdots + \lambda_k , \end{aligned} \]

using Step 3 for each \(\vect{q}_j\) and \(\mat{C}\vect{q}_j = \lambda_j\vect{q}_j\) with \(\vect{q}_j\T\vect{q}_j = 1\). With \(k = d\) this is all of \(\operatorname{tr}(\mat{C})\).

Summary card

The principal directions are the eigenvectors of the covariance matrix.

The anchor figure again: four blue points, their mean, and the pale orange first principal direction of slope 0.618 through the mean, with each point's shadow on the line and its purple perpendicular gap.
M03.6.3-F1

Most spread, smallest gaps.

  • Centre and form. \(\mat{C} = {\mat{X}_c\T\mat{X}_c/(n - 1)}\).
  • Variance along \(\vect{u}\). \(\vect{u}\T\mat{C}\vect{u}\), largest (\(\lambda_1\)) at \(\vect{q}_1\).
  • Explained variance. \({\lambda_j/\operatorname{tr}(\mat{C})}\).
  • Pythagoras. Largest variance along a line means smallest perpendicular gaps to it.

Sources and next steps

Sources. Each was opened and checked against this lesson on 15 November 2026.

  • David Austin, Understanding Linear Algebra, Principal component analysis. The variance of demeaned data in the direction of a unit vector \(\vect{u}\) is the quadratic form \({\vect{u} \cdot (C\vect{u})}\), the principal components are the eigenvectors of the covariance matrix in order of decreasing eigenvalue, and projecting onto the first \(n\) of them keeps the sum of the first \(n\) eigenvalues. Austin stores the points as columns and divides by \(N\), not \(N - 1\).
  • Marc Deisenroth, Aldo Faisal and Cheng Soon Ong, Mathematics for Machine Learning, Chapter 10. Equation (10.1) defines the data covariance matrix of centred data; Section 10.2 derives PCA as maximising the variance of the projected data, and Section 10.3 as minimising the reconstruction error, the two views of Result 4.
  • NumPy, numpy.linalg.eigh: for a symmetric matrix it returns the eigenvalues in ascending order and the normalised eigenvectors as columns.

Next. M03.6.4 PCA by SVD, in practice gets the same directions without ever forming \(\mat{C}\), and applies them to real measurements.

This lesson unlocks

M03.6.4 PCA by SVD, in practice

Your progress is saved in this browser only. No account, no tracking.
Back to top