easiest way to construct an orthogonal vector in R

Viewed 1683

How would I construct an orthogonal vector to two existing vectors, v1 and v2?

[Unfortunately, stackoverflow wants some more prose here or complains that it does not meet standards.]

3 Answers

In base R, given any two vectors, the ORTHOGONAL vector can be obtained by:

 a <- rbind(v1, v2)
 orth.vec <- sapply(seq(ncol(a)), function(x)(-1)^(x-1)*det(a[,-x]))

if you need to normalize it, ie the orthonormal vector:

 orth.vec/norm(orth.vec,"2")

EDIT: Note that this code is the same whether given n vectors. ie a must be a matrix of dimensions: n x (n + 1)

eg: Compare the two results below:

a <- matrix(sample(90),9)
MASS::Null(t(a))
             [,1]
 [1,] -0.16836356
 [2,] -0.41335337
 [3,]  0.55917161
 [4,] -0.36823759
 [5,] -0.16845300
 [6,]  0.29331428
 [7,]  0.09284215
 [8,]  0.10840769
 [9,] -0.13890032
[10,]  0.44547280

get_orth_vec <- function(y)sapply(seq(ncol(y)), function(x)(-1)^(x-1)*det(y[,-x]))

# Unnormalized Orthogonal Vector
orth.vec <- get_orth_vec(a)
 [1]  2.418607e+15  5.937980e+15 -8.032715e+15  5.289874e+15  2.419892e+15 -4.213572e+15 -1.333713e+15
 [8] -1.557318e+15  1.995356e+15 -6.399388e+15
 # Orthonormal vector
 orth.vec/norm(orth.vec,"2")
 [1]  0.16836356  0.41335337 -0.55917161  0.36823759  0.16845300 -0.29331428 -0.09284215 -0.10840769
 [9]  0.13890032 -0.44547280

Note that the only difference between the two is the direction. If you have larger matrices, use the packages since they use the qr decomposition

the easiest way may well be an abuse of the ols model:

orthogonal.vector <- resid( lm( rnorm(length(v1)) ~ v1 + v2 ) )

example:

> v1 <- rnorm(5); v2 <- rnorm(5);
> orthogonal.vector <- resid( lm( rnorm(length(v1)) ~ v1 + v2 ) )
> orthogonal.vector %*% v1
                       [,1]
[1,] -0.0000000000000004441
> orthogonal.vector %*% v2
                     [,1]
[1,] 0.000000000000000111

Maybe you can try null from pracma package, e.g.,

vout <- pracma::null(M)

or Null from MASS, e.g.,

vout <- MASS::Null(t(M))

such that

> M%*%vout
            [,1]
v1 -2.220446e-16
v2  4.440892e-16

Data

v1 <- c(1,2,3)
v2 <- c(3,2,4)
M <- rbind(v1,v2)
Related