在R中构造正交向量的最简单方法

3
我如何构造一个垂直于两个已知向量v1v2的向量?

可能相关的链接:https://math.stackexchange.com/questions/501949/determining-a-perpendicular-vector-to-two-given-vectors 和 https://dev59.com/zJbfa4cB1Zd3GeqPsVu4#36802067 - chinsoon12
3个回答

4
在基本R中,给定任意两个向量,可以通过以下方式获得垂直向量:
 a <- rbind(v1, v2)
 orth.vec <- sapply(seq(ncol(a)), function(x)(-1)^(x-1)*det(a[,-x]))

如果需要对其进行归一化,即规范正交向量:

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

编辑: 请注意,无论给定多少个向量,此代码都相同。即 a 必须是一个维度为 n x (n + 1) 的矩阵。

例如:比较下面两个结果:

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

请注意,这两者之间唯一的区别是方向。如果您有更大的矩阵,请使用这些包,因为它们使用QR分解。

1
很好的回答,自制食谱,点赞! - ThomasIsCoding

1

最简单的方法可能是滥用旧模型:

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

例子:
> 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

从技术上讲,这并不完全正确。c(0,0,0)是原点,而不是正交向量。 - Onyambu
请详细说明:结果并非源。 - ivo Welch
因为你是随机生成的,但残差需要为零。如果模型完全匹配,则残差为零。请再试一次。 - Onyambu
完美适配模型y是一个零概率事件,对于随机抽取的y向量而言。在这种情况下,可以使用另一个随机抽取的向量重新进行操作。 - ivo Welch
我尝试了5次,每一次都得到残差为c(0,0,0)。这不是一个正交向量。 - Onyambu
显示剩余2条评论

1
也许你可以尝试使用来自“pracma”包的null,例如,
vout <- pracma::null(M)

或者从 MASS 返回 Null,例如:

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

such that

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

数据

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接