Попарное расстояние двух матриц R - PullRequest
0 голосов
/ 02 мая 2019

Я хочу пробежать расстояние между матрицей в R. В этом примере я использую манхэттенское расстояние, но я хотел бы применить другие формулы.У меня вопрос, есть ли один способ применить функцию к строке матрицы за строкой другой матрицы в R?

В этом примере у меня есть только две переменные, но я хотел бы применить с более чем 10 переменных.

Спасибо.

set.seed(123)
mat1 <- data.frame(x=sample(1:10000,3), 
                   z=sample(1:10000,3))
mat2 <- data.frame(x=sample(1:100,3), 
                   z=sample(1:1000,3))

dista<-matrix(0,ncol=2,nrow=2)
for (j in 1:nrow(mat1)){
  for(i in 1:nrow(mat2)){
    dista[i,j]<-sqrt((mat1[i,1]-mat2[j,1]) + (mat1[i,2]-mat2[j,2]))
  }
}

dista

Ответы [ 2 ]

1 голос
/ 04 мая 2019

Для этих проблем можно использовать пакет proxy. По умолчанию proxy::dist рассматривает каждую строку матрицы или фрейма данных как один "объект".

library(proxy)

proxy::dist(mat1, mat2, method="Manhattan")
     [,1]  [,2]  [,3] 
[1,]  4804  4832  4656
[2,]  3708  3736  3560
[3,] 17407 17435 17259

proxy::dist(mat1, mat2, method="Euclidean")
     [,1]      [,2]      [,3]     
[1,]  3397.036  3417.059  3295.962
[2,]  2761.996  2787.495  2708.075
[3,] 12308.674 12328.422 12204.286

Введите vignette("overview", "proxy") в консоли R, чтобы увидеть, какие сходства и расстояния она включает, и проверьте документацию proxy::pr_DB, если вы хотите добавить свои собственные функции, которые можно использовать с proxy::dist.

0 голосов
/ 02 мая 2019

Ваш код по-прежнему неверен, поскольку выходные данные должны иметь длину nrow(mat1) * nrow(mat2), равную 9, и не могут вписаться в матрицу 2x2 (которую вы ранее определили). Кроме того, i должен проходить через mat1 и j через mat2; у вас все наоборот. Изменив dista[i,j] <- на print(), вы получите:

dista<-matrix(0,ncol=2,nrow=2)
for (i in 1:nrow(mat1)){
    for(j in 1:nrow(mat2)){
        print(sqrt((mat1[i,1]-mat2[j,1]) + (mat1[i,2]-mat2[j,2])))
    }
}
[1] 105.8159
[1] 129.5261
[1] 63.52165
[1] 103.257
[1] 127.4441
[1] 59.1608
[1] 105.8253
[1] 129.5338
[1] 63.53739

Вы можете использовать outer, чтобы ограничить вычисления только одной векторизованной функцией

y = outer(1:nrow(mat1),1:nrow(mat2),paste)
y
     [,1]  [,2]  [,3] 
[1,] "1 1" "1 2" "1 3"
[2,] "2 1" "2 2" "2 3"
[3,] "3 1" "3 2" "3 3"

sapply(as.vector(y), function(x){
  aux = as.numeric(strsplit(x," ")[[1]])
  sqrt((mat1[aux[1],1]-mat2[aux[2],1]) + (mat1[aux[1],2]-mat2[aux[2],2]))})

      1 1       2 1       3 1       1 2       2 2       3 2       1 3       2 3       3 3 
105.81588 129.52606  63.52165 103.25696 127.44411  59.16080 105.82533 129.53378  63.53739 

Здесь мы сначала создаем матрицу y, которая содержит все комбинации i и j, передает ее в sapply, а затем разделяет ее, чтобы получить i и j по отдельности.

...