Skip to content

Eigenvectors of point set

Martijn Koopman edited this page Jun 13, 2019 · 5 revisions

Given a set of points in 2D space. Find the vector that is parallel to the direction of dispersion and the vector that is orthogonal to this direction (normal vector).

10 input points: (1,1), (6,4), (3,2), (4,3), (4,2), (2,2), (5,3), (3,3), (2,1), (5,4)

Eigenvectors

C++

#include <spatium/stats.h>

using namespace spatium;

// Construct matrix (10 rows, 2 columns)
Matrix m({ {1,1}, {6,4}, {3,2}, {4,3}, {4,2}, {2,2}, {5,3}, {3,3}, {2,1}, {5,4} });

// Compute covariance matrix
Matrix covMatrix = stats::covariance(m);

// Compute eigenvalues
double eigval1, eigval2; 
stats::eigenvalues2(covMatrix, eigval1, eigval2) // 0.172671 and 3.12733

// Compute corresponding eigen vectors
std::vector<double> eigvec1(2), eigvec2(2);
stats::eigenvector2(covMatrix, eigval1, eigvec1); // 1.35, -2.07733
stats::eigenvector2(covMatrix, eigval2, eigvec2); // 1.35, 0.877329

You may want to normalize and flip the vectors. The flipped vectors are also valid solutions.

#include <spatium/geom2d.h>

// Construct 2D vectors
geom2d::Vector2 vec1(eigvec1);
geom2d::Vector2 vec2(eigvec2);

// Normalize vectors
vec1.normalize(); // 0.544914, -0.838492
vec2.normalize(); // 0.838492, 0.544914

Note that both vectors are orthogonal. We can validate this via the dot product. vec1.dot(vec2) == 0 The dot product of two normalized orthogonal vectors is (close to) zero.

MATLAB/Octave equivalent

x = [1, 6, 3, 4, 4, 2, 5, 3, 2, 5]
y = [1, 4, 2, 3, 2, 2, 3, 3, 1, 4]

# Compute mean of both variables
x_mean = mean(x)
y_mean = mean(y)

# Compute variance and covariance
x_var = var(x,1)
y_var = var(y,1)
xy_var = cov(x,y,1)

# Construct covariance matrix
cov_mat = [x_var, xy_var; xy_var, y_var]

# Compute eigenvalues and eigenvectors
[eigvecs,eigvals] = eig(cov_mat,"vector")

# eigvals
# 0.17267
# 3.12733

#eigvecs:
# (0.54491, -0.83849)   
# (-0.83849,  -0.54491)

Clone this wiki locally