R中向量和向量列表之间的角度
Angle between vector and list of vectors in R
当比较两个向量时,计算它们之间的角度很简单,但在 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)) ) ))
它失败了,因为它们是不一致的参数。
有没有和上面类似的代码可以处理向量和矩阵?
注意:存在被标记为重复的风险,在几个 sources 中找到的解决方案不适用于这种情况
编辑:这样做的原因是我有一个大矩阵 X
,而 A
只是其中的一行。我仅根据每个向量的角度来减少元素的数量。 B
的第一个元素是X
中的第一个,然后如果B
中任意一个元素与下一个元素X[,2]
的夹角(这里是A
)大于一定的公差,这被添加到列表 B
。我只是使用 B<-rbind(B,X[,2])
来执行此操作,因此这导致 B
成为矩阵。
你没有详细描述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
解决方案 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
解决方案 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
B
的行与向量A
的点积向量为B %*% A
。 B
行的矢量长度为sqrt(rowSums(B^2))
。
要找到最小的角度,您需要最大的余弦,但实际上您不需要计算角度,所以 A
的长度无关紧要。
因此角度最小的行将由row <- which.max((B %*% A)/sqrt(rowSums(B^2)))
给出。对于 Darren 的数据,这是第 1 行。
如果确实需要最小角度,那么可以将两个向量的公式应用于B[row,]
和A
。如果您需要所有角度,则公式为
acos((B %*% A)/sqrt(rowSums(B^2))/sqrt(sum(A^2)))
当比较两个向量时,计算它们之间的角度很简单,但在 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)) ) ))
它失败了,因为它们是不一致的参数。
有没有和上面类似的代码可以处理向量和矩阵?
注意:存在被标记为重复的风险,在几个 sources 中找到的解决方案不适用于这种情况
编辑:这样做的原因是我有一个大矩阵 X
,而 A
只是其中的一行。我仅根据每个向量的角度来减少元素的数量。 B
的第一个元素是X
中的第一个,然后如果B
中任意一个元素与下一个元素X[,2]
的夹角(这里是A
)大于一定的公差,这被添加到列表 B
。我只是使用 B<-rbind(B,X[,2])
来执行此操作,因此这导致 B
成为矩阵。
你没有详细描述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
解决方案 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
解决方案 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
B
的行与向量A
的点积向量为B %*% A
。 B
行的矢量长度为sqrt(rowSums(B^2))
。
要找到最小的角度,您需要最大的余弦,但实际上您不需要计算角度,所以 A
的长度无关紧要。
因此角度最小的行将由row <- which.max((B %*% A)/sqrt(rowSums(B^2)))
给出。对于 Darren 的数据,这是第 1 行。
如果确实需要最小角度,那么可以将两个向量的公式应用于B[row,]
和A
。如果您需要所有角度,则公式为
acos((B %*% A)/sqrt(rowSums(B^2))/sqrt(sum(A^2)))