-
Notifications
You must be signed in to change notification settings - Fork 6
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)

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.877329You 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.544914Note 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)