Ângulo entre dois vectores em R
Qual a forma mais eficiente na linguagem de programação r para calcular o ângulo entre dois vectores?
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)) ) )
Parte 1 - Matemática
O produto Ponto de dois vectores x e y pode ser definido como:
Onde / / x / / é a norma Euclidiana (também conhecida como a L2 norm) do vector x .
Manipular o definição do produto Ponto, podemos obter:
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: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!
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
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
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 comoV₁·V₂ = x₁·x₂ + y₁·y₂ + z₁·z₂ = |V₁| · |V₂| · cos(θ);
Então, se reorganizares a primeira equação acima, terás|V₁| = √(x₁2 + y₁2 + z₁2), e
|V₂| = √(x₂2 + y₂2 + z₂2),
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
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 poracos(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)))
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: