R中两个向量之间的角度

Chr*_*ian 29 math geometry r computational-geometry

编程语言R中最有效的方法是计算两个向量之间的角度?

las*_*ock 45

据第5页这个PDF,sum(a*b)是R命令查找向量的点积ab,和sqrt(sum(a * a))是R命令找到载体的规范a,并且acos(x)对于反余弦R命令.由此得出,计算两个矢量之间的角度的R代码是

theta <- acos( sum(a*b) / ( sqrt(sum(a * a)) * sqrt(sum(b * b)) ) )
Run Code Online (Sandbox Code Playgroud)

  • @ user1965813同意。`atan2`函数是解决方法(请参阅我的答案)。 (2认同)

Gra*_*lsh 19

我的答案由两部分组成.第1部分是数学 - 为线程的所有读者提供清晰度,并使R代码可以理解.第2部分是R编程.

第1部分 - 数学

两个向量xy的点积可以定义为:

在此输入图像描述

在哪里|| x || 是向量x的欧几里德范数(也称为L 2范数).

操纵点积的定义,我们可以得到:

在此输入图像描述

其中θ是以弧度表示的向量xy之间的角度.请注意,theta可以采用位于从0到pi的闭合间隔的值.

解决theta本身,我们得到:

在此输入图像描述

第2部分 - R代码

要将数学转换为R代码,我们需要知道如何执行两个矩阵(向量)计算; 点积和欧几里德范数(这是一种特定类型的范数,称为L 2范数).我们还需要知道反余弦函数的R等价物,cos -1.

从顶部开始.通过参考?"%*%",可以使用%*%操作员计算点积(也称为内积).参考?norm,norm()函数(基础包)返回向量范数.这里感兴趣的规范是L 2范数,或者在R帮助文档的说法中,是"频谱"或"2"范数.这意味着函数的type参数norm()应该设置为等于"2".最后,R中的反余弦函数由acos()函数表示.

配备了数学和相关的R函数,原型函数(即非生产标准)可以放在一起 - 使用Base包函数 - 如下所示.如果上述信息有意义,那么下面的angle()函数应该是清楚的,没有进一步的评论.

angle <- function(x,y){
  dot.prod <- x%*%y 
  norm.x <- norm(x,type="2")
  norm.y <- norm(y,type="2")
  theta <- acos(dot.prod / (norm.x * norm.y))
  as.numeric(theta)
}
Run Code Online (Sandbox Code Playgroud)

测试功能

验证该功能是否有效的测试.设x =(2,1)和y =(1,2).xy之间的点积是4.欧几里德范数x是sqrt(5).y的欧几里德范数也是sqrt(5).cos theta = 4/5.Theta约为0.643弧度.

x <- as.matrix(c(2,1))
y <- as.matrix(c(1,2))
angle(t(x),y)          # Use of transpose to make vectors (matrices) conformable.
[1] 0.6435011
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助!

  • 总是喜欢包含其背后数学原理的答案!使用“norm”也+1。我见过 `sqrt(a * a)` 的次数...... (3认同)

Sté*_*ent 13

对于2D矢量,接受的答案和其他答案中给出的方式没有考虑角度的方向(符号)(与之angle(M,N)相同angle(N,M)),并且仅针对0和之间的角度返回正确的值pi.

使用该atan2函数可以获得定向角度和正确的值(模数2pi).

angle <- function(M,N){
  acos( sum(M*N) / ( sqrt(sum(M*M)) * sqrt(sum(N*N)) ) )
}
angle2 <- function(M,N){
  atan2(N[2],N[1]) - atan2(M[2],M[1]) 
}
Run Code Online (Sandbox Code Playgroud)

检查是否angle2给出了正确的值:

> theta <- seq(-2*pi, 2*pi, length.out=10)
> O <- c(1,0)
> test1 <- sapply(theta, function(theta) angle(M=O, N=c(cos(theta),sin(theta))))
> all.equal(test1 %% (2*pi), theta %% (2*pi))
[1] "Mean relative difference: 1"
> test2 <- sapply(theta, function(theta) angle2(M=O, N=c(cos(theta),sin(theta))))
> all.equal(test2 %% (2*pi), theta %% (2*pi))
[1] TRUE
Run Code Online (Sandbox Code Playgroud)


Joh*_*ner 7

你应该使用点积.假设你有V 1 =(x 1,y 1,z 1)和V 2 =(x 2,y 2,z 2),那么我将用VV 2 表示的点积计算如

VV 2 = xx 2 + yy 2 + zz 2 = | V 1 | ·| V 2 | ·cos(θ);

这意味着左边显示的总和等于矢量的绝对值乘以矢量之间角度的余弦的乘积.矢量V 1和V 2 的绝对值计算如下

| V 1 | =√(x 12 + y 12 + z 12)和
| V 2 | =√(x 22 + y 2 + + z 2),

所以,如果你重新排列上面的第一个等式,你就得到了

cos(θ)=(xx 2 + yy 2 + zz 2)÷(| V 1 |·| V 2 |),

你只需要将arccos函数(或反余弦)应用于cos(θ)来获得角度.

根据您的arccos函数,角度可以是度或弧度.

(对于二维向量,只需忘记z坐标并进行相同的计算.)

祝好运,

约翰多纳

  • *其中*是R中的点积?这是一个基本/常见的操作,似乎不需要对其进行编码.我已经看到一些关于sum(a*b)作为点积的噪音:但是R惯用法是什么? (2认同)

小智 5

另一种解决方案:两个向量之间的相关性等于两个向量之间的角度的余弦值。

因此角度可以通过 acos(cor(u,v))

# example u(1,2,0) ; v(0,2,1)

cor(c(1,2),c(2,1))
theta = acos(cor(c(1,2),c(2,1)))
Run Code Online (Sandbox Code Playgroud)


小智 5

如果您安装/上传库(matlib):有一个名为 angle(x, y, degree = TRUE) 的函数,其中 x 和 y 是向量。注意:如果您有矩阵形式的 x 和 y,请使用 as.vector(x) 和 as.vector(y):

library(matlib)
matA <- matrix(c(3, 1), nrow = 2)  ##column vectors
matB <- matrix(c(5, 5), nrow = 2)
angle(as.vector(matA), as.vector(matB))  
##default in degrees, use degree = FALSE for radians
Run Code Online (Sandbox Code Playgroud)