Angle between two vectors in R
Solution 1:
According to page 5 of this PDF, sum(a*b)
is the R command to find the dot product of vectors 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. It follows that the R code to calculate the angle between the two vectors is
theta <- acos( sum(a*b) / ( sqrt(sum(a * a)) * sqrt(sum(b * b)) ) )
Solution 2:
My answer consists of two parts. Part 1 is the math - to give clarity to all readers of the thread and to make the R code that follows understandable. Part 2 is the R programming.
Part 1 - Math
The dot product of two vectors x and y can be defined as:
where ||x|| is the Euclidean norm (also known as the L2 norm) of the vector x.
Manipulating the definition of the dot product, we can obtain:
where theta is the angle between the vectors x and y expressed in radians. Note that theta can take on a value that lies on the closed interval from 0 to pi.
Solving for theta itself, we get:
Part 2 - R Code
To translate the mathematics into R code, we need to know how to perform two matrix (vector) calculations; dot product and Euclidean norm (which is a specific type of norm, known as the L2 norm). We also need to know the R equivalent of the inverse cosine function, cos-1.
Starting from the top. By reference to ?"%*%"
, the dot product (also referred to as the inner product) can be calculated using the %*%
operator. With reference to ?norm
, the norm()
function (base package) returns a norm of a vector. The norm of interest here is the L2 norm or, in the parlance of the R help documentation, the "spectral" or "2"-norm. This means that the type
argument of the norm()
function ought to be set equal to "2"
. Lastly, the inverse cosine function in R is represented by the acos()
function.
Solution
Equipped with both the mathematics and the relevant R functions, a prototype function (that is, not production standard) can be put together - using Base package functions - as shown below. If the above information makes sense then the angle()
function that follows should be clear without further comment.
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)
}
Test the function
A test to verify that the function works. Let x = (2,1) and y = (1,2). Dot product between x and y is 4. Euclidean norm of x is sqrt(5). Euclidean norm of y is also sqrt(5). cos theta = 4/5. Theta is approximately 0.643 radians.
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
I hope this helps!