[英]Angle between vector and list of vectors in R
When comparing two vectors it is simple to calculate the angle between them, but in R it is noticeably harder to calculate the angle between a vector and a matrix of vectors efficiently. 当比较两个矢量时,计算它们之间的角度很简单,但是在R中,有效地计算矢量和矢量矩阵之间的角度明显更困难。
Say you have a 2D vector A=(2, 0) and then a matrix B={(1,3), (-2,4), (-3,-3), (1,-4)}. 假设您有2D矢量A =(2,0),然后矩阵B = {(1,3),( - 2,4),( - 3,-3),(1,-4)}。 I am interested in working out the smallest angle between A and the vectors in B. If I try to use 我有兴趣计算A和B中矢量之间的最小角度。如果我尝试使用
min(acos( sum(a%*%b) / ( sqrt(sum(a %*% a)) * sqrt(sum(b %*% b)) ) ))
it fails as they are non-conformable arguments. 它失败了,因为它们是不一致的参数。
Is there any code similar to that of above which can handle a vector and matrix? 有没有类似上面的代码可以处理向量和矩阵?
Note: At the risk of being marked as a duplicate the solutions found in several sources do not apply in this case 注意:存在被标记为重复的风险,在这种情况下,在多个来源中找到的解决方案不适用
Edit: The reason for this is I have a large matrix X
, and A
is just one row of this. 编辑:原因是我有一个大的矩阵X
,而A
只是这一行的一行。 I am reducing the number of elements based solely on the angle of each vector. 我仅根据每个矢量的角度减少元素的数量。 The first element of B
is the first in X
, and then if the angle between any element in B
and the next element X[,2]
(here A
) is greater than a certain tolerance, this is added to the list B
. B
的第一个元素是X
的第一个元素,然后如果B
任何元素与下一个元素X[,2]
(此处为A
)之间的角度大于某个容差,则将其添加到列表B
。 I am just using B<-rbind(B,X[,2])
to do this, so this results in B
being a matrix. 我只是使用B<-rbind(B,X[,2])
来做这个,所以这导致B
是一个矩阵。
You don't describe the format of A and B in detail, so I assume they are matrices by rows. 您没有详细描述A和B的格式,因此我假设它们是行的矩阵。
(A <- c(2, 0))
# [1] 2 0
(B <- rbind(c(1,3), c(-2,4), c(-3,-3), c(1,-4)))
# [,1] [,2]
# [1,] 1 3
# [2,] -2 4
# [3,] -3 -3
# [4,] 1 -4
Solution 1 with apply()
: 使用apply()
解决方案1 :
apply(B, 1, FUN = function(x){
acos(sum(x*A) / (sqrt(sum(x*x)) * sqrt(sum(A*A))))
})
# [1] 1.249046 2.034444 2.356194 1.325818
Solution 2 with sweep()
: (replace sum()
above with rowSums()
) 溶液2 sweep()
替换sum()
上面rowSums()
sweep(B, 2, A, FUN = function(x, y){
acos(rowSums(x*y) / (sqrt(rowSums(x*x)) * sqrt(rowSums(y*y))))
})
# [1] 1.249046 2.034444 2.356194 1.325818
Solution 3 with split()
and mapply
: 解决方案3与split()
和mapply
:
mapply(function(x, y){
acos(sum(x*y) / (sqrt(sum(x*x)) * sqrt(sum(y*y))))
}, split(B, row(B)), list(A))
# 1 2 3 4
# 1.249046 2.034444 2.356194 1.325818
The vector of dot products between the rows of B
and the vector A
is B %*% A
. B
行与矢量A
之间的点积矢量为B %*% A
。 The vector lengths of the rows of B
are sqrt(rowSums(B^2))
. B
行的向量长度是sqrt(rowSums(B^2))
。
To find the smallest angle, you want the largest cosine, but you don't actually need to compute the angle, so the length of A
doesn't matter. 要找到最小的角度,您需要最大的余弦,但实际上并不需要计算角度,因此A
的长度无关紧要。
Thus the row with the smallest angle will be given by row <- which.max((B %*% A)/sqrt(rowSums(B^2)))
. 因此,具有最小角度的row <- which.max((B %*% A)/sqrt(rowSums(B^2)))
将由row <- which.max((B %*% A)/sqrt(rowSums(B^2)))
。 With Darren's data, that's row 1. 根据Darren的数据,这是第1行。
If you really do need the smallest angle, then you can apply the formula for two vectors to B[row,]
and A
. 如果确实需要最小角度,则可以将两个向量的公式应用于B[row,]
和A
If you need all of the angles, then the formula would be 如果你需要所有的角度,那么公式就是
acos((B %*% A)/sqrt(rowSums(B^2))/sqrt(sum(A^2)))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.