Eigenvalues and Eigenvectors
Compute eigen decompositions with eigen() and interpret results.
Eigenvalues and Eigenvectors is a free R Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the R Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Are Eigenvalues?
An eigenvector v of matrix A is a non-zero vector that only scales (not rotates) when multiplied by A: Av = λv. The scalar λ is the eigenvalue. They reveal a matrix's intrinsic stretching directions.
# Intuition: A simple scaling matrix
A <- matrix(c(3, 0,
0, 2), nrow = 2, byrow = TRUE)
# The eigenvectors are the standard basis vectors
# A * c(1,0) = 3 * c(1,0) -> eigenvalue 3
# A * c(0,1) = 2 * c(0,1) -> eigenvalue 2
v1 <- c(1, 0)
A %*% v1 # c(3, 0) = 3 * v1
v2 <- c(0, 1)
A %*% v2 # c(0, 2) = 2 * v2
cat('Eigenvalues of a diagonal matrix are its diagonal entries')eigen(): Computing Eigenvalues
eigen(A) returns a list with $values (eigenvalues sorted by decreasing magnitude) and $vectors (matrix of eigenvectors as columns). The eigenvectors are normalized to unit length.
A <- matrix(c(4, 1,
2, 3), nrow = 2, byrow = TRUE)
# Compute eigendecomposition
eig <- eigen(A)
# Eigenvalues
eig$values
# [1] 5 2 (descending order)
# Eigenvectors (columns)
eig$vectors
# [,1] [,2]
# [1,] 0.7071068 -0.4472136
# [2,] 0.7071068 0.8944272
cat('Each column is one eigenvector (unit length)')Verifying Av = lambda * v
To verify, check that A %*% v - lambda * v is essentially zero. Due to floating point, use max(abs(...)) and check it's near machine epsilon rather than testing exact equality.
A <- matrix(c(4, 1,
2, 3), nrow = 2, byrow = TRUE)
eig <- eigen(A)
lambda1 <- eig$values[1] # 5
v1 <- eig$vectors[, 1]
# Verify: Av - lambda*v should be ~0
residual <- A %*% v1 - lambda1 * v1
max(abs(residual)) # ~ 1e-16
# Check all eigenpairs at once
# A V = V diag(lambda) where V = eigenvectors matrix
V <- eig$vectors
Lambda <- diag(eig$values)
err <- A %*% V - V %*% Lambda
max(abs(err)) # near zeroSymmetric Matrices: Real Eigenvalues
Symmetric matrices (A = t(A)) always have real eigenvalues and orthogonal eigenvectors. This is the spectral theorem — essential in statistics (covariance matrices are symmetric positive semi-definite).
# Symmetric matrix
S <- matrix(c(4, 2, 2,
2, 3, 1,
2, 1, 5), nrow = 3, byrow = TRUE)
# All symmetric: A = t(A)
all.equal(S, t(S)) # TRUE
# Eigenvalues are real
eig <- eigen(S)
eig$values # All real numbers
Im(eig$values) # All zero
# Eigenvectors are orthogonal: V'V = I
V <- eig$vectors
round(t(V) %*% V, 10) # Identity matrix
cat('Symmetric -> real eigenvalues, orthogonal eigenvectors')Asymmetric Matrices: Complex Eigenvalues
Non-symmetric matrices can have complex eigenvalues (complex conjugate pairs). R returns them as complex numbers. The real part governs growth/decay; the imaginary part governs rotation/oscillation.
# Rotation-like matrix -> complex eigenvalues
A <- matrix(c(0, -1,
1, 0), nrow = 2, byrow = TRUE)
# This is a 90-degree rotation matrix
eig <- eigen(A)
eig$values
# [1] 0+1i 0-1i (pure imaginary!)
# Real part: zero -> neither grows nor decays
Re(eig$values) # 0 0
# Imaginary part: indicates rotation
Im(eig$values) # 1 -1
# Another example: stable spiral
B <- matrix(c(-1, -2,
2, -1), nrow = 2, byrow = TRUE)
eigen(B)$values # -1 +/- 2iEigenvalue Decomposition A = VLV^-1
A diagonalizable matrix A can be written as A = V Λ V⁻¹, where V is the eigenvector matrix and Λ = diag(eigenvalues). This decomposition unlocks matrix powers: A^n = V Λ^n V⁻¹.
A <- matrix(c(4, 1,
2, 3), nrow = 2, byrow = TRUE)
eig <- eigen(A)
V <- eig$vectors
Lambda <- diag(eig$values)
# Reconstruct A = V %*% Lambda %*% solve(V)
A_reconstructed <- V %*% Lambda %*% solve(V)
all.equal(A, A_reconstructed) # TRUE
# Matrix power A^3 using eigendecomposition
A_cubed_eig <- V %*% diag(eig$values^3) %*% solve(V)
A_cubed_direct <- A %*% A %*% A
all.equal(Re(A_cubed_eig), A_cubed_direct) # TRUEPCA Concept via Covariance Eigenvalues
Principal Component Analysis (PCA) uses eigendecomposition of the covariance matrix. Eigenvectors give the directions of maximum variance (principal components); eigenvalues give the variance along each direction.
set.seed(42)
# Correlated 2D data
x1 <- rnorm(100)
x2 <- 0.8 * x1 + 0.6 * rnorm(100)
X <- cbind(x1, x2)
# Covariance matrix
C <- cov(X)
print(round(C, 3))
# Eigendecomposition of covariance matrix
eig <- eigen(C)
cat('Eigenvalues (variance explained):\n')
print(eig$values)
cat('PC1 direction:\n')
print(eig$vectors[, 1])
# Variance explained by PC1
prop_var <- eig$values[1] / sum(eig$values)
cat('PC1 explains:', round(100 * prop_var, 1), '%')Spectral Radius
The spectral radius ρ(A) = max|λᵢ| is the largest absolute eigenvalue. It determines stability in iterative algorithms: if ρ < 1, iterations converge; if ρ > 1, they diverge.
spectral_radius <- function(A) {
max(Mod(eigen(A)$values))
}
# Convergent matrix: spectral radius < 1
A_conv <- matrix(c(0.5, 0.2,
0.1, 0.3), nrow = 2, byrow = TRUE)
spectral_radius(A_conv) # < 1 -> iterations converge
# Divergent matrix: spectral radius > 1
A_div <- matrix(c(2, 0.5,
0.3, 1.5), nrow = 2, byrow = TRUE)
spectral_radius(A_div) # > 1 -> iterations diverge
# For positive definite A, spectral radius = max eigenvalue
cat('Spectral radius determines iterative stability')Determinant and Trace via Eigenvalues
The determinant equals the product of eigenvalues; the trace equals their sum. These relationships connect algebraic properties to eigenvalues and provide sanity checks for your eigen() results.
A <- matrix(c(5, 2,
1, 4), nrow = 2, byrow = TRUE)
eig_vals <- eigen(A)$values
# det(A) = product of eigenvalues
det(A)
prod(eig_vals) # Same!
# trace = sum of eigenvalues
sum(diag(A))
sum(eig_vals) # Same!
# For numeric precision, use Re() on complex
A2 <- matrix(c(3, -1, 2, 5), nrow = 2, byrow = TRUE)
ev <- eigen(A2)$values
all.equal(det(A2), prod(Re(ev)), tolerance = 1e-10)
all.equal(sum(diag(A2)), sum(Re(ev)), tolerance = 1e-10)Positive Definite Matrices
A symmetric matrix is positive definite (PD) if all eigenvalues are positive. Covariance matrices are positive semi-definite (eigenvalues ≥ 0). PD matrices are invertible and have Cholesky decompositions.
# Check positive definiteness
is_positive_definite <- function(A) {
# Symmetric check
if (!isTRUE(all.equal(A, t(A)))) return(FALSE)
all(eigen(A)$values > 0)
}
# Positive definite covariance matrix
S <- matrix(c(4, 2,
2, 3), nrow = 2, byrow = TRUE)
is_positive_definite(S) # TRUE
eigen(S)$values # Both positive
# Not PD (one negative eigenvalue)
Q <- matrix(c(1, 3,
3, 2), nrow = 2, byrow = TRUE)
is_positive_definite(Q) # FALSE
eigen(Q)$values # One negativePower Iteration for Dominant Eigenvalue
For large matrices, computing all eigenvalues is expensive. Power iteration finds the largest eigenvalue iteratively — the basis of Google's PageRank algorithm. Multiply by A repeatedly, then normalize.
# Power iteration: finds dominant eigenvalue
power_iteration <- function(A, tol = 1e-10, max_iter = 1000) {
n <- nrow(A)
v <- rnorm(n); v <- v / sqrt(sum(v^2)) # random unit vector
lambda_old <- 0
for (i in seq_len(max_iter)) {
w <- A %*% v
lambda <- max(abs(w))
v <- w / lambda
if (abs(lambda - lambda_old) < tol) break
lambda_old <- lambda
}
list(value = lambda, vector = v)
}
A <- matrix(c(4, 1, 2, 3), nrow = 2, byrow = TRUE)
result <- power_iteration(A)
result$value # Should be ~5 (dominant eigenvalue)
eigen(A)$values[1] # CompareQuick Check
Test your understanding of eigenvalues and eigenvectors in R.
Recap: Eigenvalues and Eigenvectors
Key takeaways: eigen(A) returns $values and $vectors. Verify with A %*% v - lambda*v ≈ 0. Symmetric matrices have real eigenvalues and orthogonal eigenvectors. Non-symmetric matrices may have complex eigenvalues. det(A) = product of eigenvalues; trace = sum. PCA decomposes the covariance matrix. Positive definite ↔ all eigenvalues > 0.
A <- matrix(c(6, 2, 2, 3), nrow = 2)
eig <- eigen(A)
# Key eigen operations:
eig$values # eigenvalues
eig$vectors # eigenvectors (columns)
# Verify Av = lambda*v
v1 <- eig$vectors[, 1]
max(abs(A %*% v1 - eig$values[1] * v1)) # ~0
# Properties
all.equal(det(A), prod(eig$values)) # TRUE
all.equal(sum(diag(A)), sum(eig$values)) # TRUE
# Reconstruct A = V Lambda V^{-1}
V <- eig$vectors
all.equal(A, Re(V %*% diag(eig$values) %*% solve(V)))Frequently asked questions
Is the “Eigenvalues and Eigenvectors” lesson free?
Yes — the full text of “Eigenvalues and Eigenvectors” is free to read here on the web, and the R Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the R Academy course, upgrade to CoddyKit PRO.
What will I learn in “Eigenvalues and Eigenvectors”?
Compute eigen decompositions with eigen() and interpret results. You practise R Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start R Academy?
No prior experience is required. R Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Eigenvalues and Eigenvectors” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this R Academy lesson?
Yes. Every R Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Matrix Multiplication and Determinants
- Solving Linear Systems with solve()
- Eigenvalues and Eigenvectors
- SVD, QR, and Cholesky Decompositions