R中向量与向量列表之间的夹角

4

比较两个向量时,计算它们之间的角度很简单,但在 R 中,要高效地计算一个向量和一个向量矩阵之间的角度就比较困难。

假设你有一个二维向量 A=(2, 0),然后有一个矩阵 B={(1,3), (-2,4), (-3,-3), (1,-4)}。我想知道 A 和 B 中向量之间最小的角度。 如果我尝试使用

min(acos( sum(a%*%b) / ( sqrt(sum(a %*% a)) * sqrt(sum(b %*% b)) ) ))

由于参数不兼容,因此它失败了。

是否有类似上面的代码可以处理向量和矩阵?

注意:冒着被标记为重复的风险,在几个中找到的解决方案在这种情况下不适用。

编辑:原因是我有一个大矩阵X,而A只是其中的一行。我仅基于每个向量的角度来减少元素的数量。 B的第一个元素是X中的第一个元素,然后如果B中的任何元素与下一个元素X [,2] (这里是A)之间的角度大于某个容差,则将其添加到列表B中。我只是使用B<-rbind(B,X[,2])来做到这一点,因此结果是B成为矩阵。


B是指列表还是矩阵?我想是列表。 - markus
本质上是一个列表,但我的 R 不是很好,所以它的类型为“矩阵”。 - Beavis
像这样 B=list(c(1,3), c(-2,4), c(-3,-3), c(1,-4)) - markus
我已经添加了一个编辑说明如何创建B,这回答了这个问题。 - Beavis
3
请添加一个数字示例,展示两个输入和预期输出,这将有助于回答问题。 - RLave
2个回答

2

您没有详细描述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

解决方案1使用apply()函数:

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

使用 sweep()解决方案2:(将上面的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

解决方案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 

0

向量B的行与向量A的点积向量为B %*% A。向量B的行长度为sqrt(rowSums(B^2))

要找到最小的角度,您需要最大的余弦值,但实际上您不需要计算角度,因此A的长度并不重要。

因此,具有最小角度的行将由row <- which.max((B %*% A)/sqrt(rowSums(B^2)))给出。对于达伦的数据,这是第1行。

如果您确实需要最小的角度,则可以将公式应用于B[row,]A的两个向量。如果您需要所有角度,则公式将为

acos((B %*% A)/sqrt(rowSums(B^2))/sqrt(sum(A^2)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接