Ângulo entre dois vectores em R

Qual a forma mais eficiente na linguagem de programação r para calcular o ângulo entre dois vectores?

Author: Christian, 2009-12-13

6 answers

De acordo com a Página 5 de Este PDF, sum(a*b) is the R command to find the dot product of vetors a and b, and sqrt(sum(a * a)) is the R command to find the norm of vector a, and acos(x) is the R command for the arc-cosine. Segue-se que o código R para calcular o ângulo entre os dois vetores é

theta <- acos( sum(a*b) / ( sqrt(sum(a * a)) * sqrt(sum(b * b)) ) )
 39
Author: las3rjock, 2013-07-14 17:02:22
A minha resposta consiste em duas partes. Parte 1 é a matemática - para dar clareza a todos os leitores do tópico e para fazer o código R que se segue compreensível. A parte 2 é a programação R.

Parte 1 - Matemática

O produto Ponto de dois vectores x e y pode ser definido como:

enter image description here

Onde / / x / / é a norma Euclidiana (também conhecida como a L2 norm) do vector x .

Manipular o definição do produto Ponto, podemos obter:

enter image description here

Em que theta é o ângulo entre os vectores x e y Expresso EM radianos. Note que theta pode assumir um valor que está no intervalo fechado de 0 a pi.

Resolvendo para a própria theta, temos:

enter image description here

Parte 2-Código R

Para traduzir a matemática em código R, Precisamos de saber como executar dois cálculos de matriz (vector); produto de ponto e Norma euclidiana (que é um tipo específico de norma, conhecido como L2 norm). Também precisamos saber o equivalente R da função cosseno inversa, cos-1.

A começar do início. Por referência a ?"%*%", o produto dot (também referido como o produto interno) pode ser calculado utilizando o operador %*%. Com referência a ?norm, a função norm() (Pacote base) devolve a norma de um vector. A norma de interesse aqui é o L2 o parecido com a documentação de Ajuda R, a norma "espectral" ou "2". Isto significa que o argumento type da função norm() deve ser igual a "2". Finalmente, a função cosseno inversa em R é representada pela função acos().

Solução

Equipado tanto com as funções matemáticas como com as funções R relevantes, pode ser montada uma função protótipo (isto é, não um padrão de produção) - utilizando funções de pacote de Base - como se pode ver a seguir. Se a informação acima faz sentido então a função angle() que se segue deve ser clara sem mais comentários.

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)
}

Testar a função

Um teste para verificar se a função funciona. x = (2,1) e y = (1,2). O produto Ponto entre x e y é 4. A norma euclidiana de x é sqrt (5). A norma euclidiana de y também é sqrt (5). cos theta = 4/5. Theta é de aproximadamente 0,643 radianos.

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
Espero que isto ajuda!
 16
Author: Graeme Walsh, 2014-07-29 00:16:13

Para os vectores 2D, a forma dada na resposta aceite e nos outros não tem em conta a orientação (o sinal) do ângulo (angle(M,N) é a mesma que angle(N,M)) e devolve um valor correcto apenas para um ângulo entre 0 e pi.

Utilize a função atan2 para obter um ângulo orientado e um valor correcto (modulo 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]) 
}

Verifique se angle2 dá o valor correcto:

> 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
 8
Author: Stéphane Laurent, 2018-04-03 05:03:08

Deve usar o produto dot. Digamos que você tem V₁ = (x₁, y₁, z₁) e V₂ = (x₂, y₂, z₂), então o produto escalar, o que eu vou denotar por V₁·V₂, é calculado como

V₁·V₂ = x₁·x₂ + y₁·y₂ + z₁·z₂ = |V₁| · |V₂| · cos(θ);

O que isto significa é que ... que soma mostrada à esquerda é igual ao produto dos valores absolutos dos vetores vezes o cosseno do ângulo entre os vetores. o valor absoluto dos vectores v₁ e v₂ é calculado como

|V₁| = √(x₁2 + y₁2 + z₁2), e
|V₂| = √(x₂2 + y₂2 + z₂2),

Então, se reorganizares a primeira equação acima, terás

Cos(θ) = (x₁·x₂ + y₁·y₂ + z₁·z₂) ÷ (|V₁|·|V₂|),

E você só precisa da função arccos (ou cosseno inverso) aplicada a cos ( θ ) para obter o ângulo.

Dependendo da sua função arccos, o ângulo pode estar em graus ou radianos.

(para vectores bidimensionais, basta esquecer asZ -coordenadas e fazer os mesmos cálculos.)

Ainda bem. sorte,

John Doner

 6
Author: John R Doner, 2015-10-07 10:25:06

Outra solução: a correlação entre os dois vectores é igual ao cosseno do ângulo entre dois vectores.

Então o ângulo pode ser calculado por 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)))
 4
Author: Mohamed, 2013-08-20 09:12:49
Acho que o que precisas é de um produto interno. Para dois vectores v,u (em R^n ou quaisquer outros espaços de interior de produtos) {[[2]}. (was alpha is the angle between the vectors)

Para mais detalhes, ver:

Http://en.wikipedia.org/wiki/Inner_product_space

 0
Author: Guy, 2009-12-13 21:35:57