Угол между вектором и списком векторов в R - PullRequest
0 голосов
/ 11 января 2019

При сравнении двух векторов просто вычислить угол между ними, но в 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 является матрицей.

Ответы [ 2 ]

0 голосов
/ 11 января 2019

Вектор точечных произведений между строками 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)))
0 голосов
/ 11 января 2019

Вы не описываете формат 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 
...