вычисление евклидова расстояния между каждой строкой фрейма данных со всеми остальными строками в другом фрейме данных

Мне нужно создать фрейм данных с минимальным евклидовым расстоянием между каждой строкой фрейма данных и всеми остальными строками другого фрейма данных. Оба моих фрейма данных большие (около 40 000 строк). Это то, что я мог решить до сих пор.

x<-matrix(c(3,6,3,4,8),nrow=5,ncol=7,byrow = TRUE)     
y<-matrix(c(1,4,4,1,9),nrow=5,ncol=7,byrow = TRUE)


sed.dist<-numeric(5)
for (i in 1:(length(sed.dist))) {
sed.dist[i]<-(sqrt(sum((y[i,1:7] - x[i,1:7])^2)))
}

Но это работает только тогда, когда i = j. Мне по существу нужно найти минимальное евклидово расстояние, перебирая каждую строку одну за другой ( y [1,1: 7], затем y [2, 1: 7] и т. д. до i= 5 ) кадра данных "y" со всеми строками кадра данных "x" (x [i, 1: 7]). Каждый раз, когда он это делает, мне нужно найти минимальное евклидово расстояние для каждого вычисления строки i кадра данных y и всех строк кадра данных x и сохранить его в другом кадре данных.


person user14845    schedule 06.03.2014    source источник
comment
Этот sqrt(colSums((y[1, ] - t(x))^2)) вычисляет расстояние строки 1 в y со всеми строками в x. Вы хотите, чтобы min этого, а также повторялось для каждой второй строки в y?   -  person alexis_laz    schedule 06.03.2014
comment
Да, это то, что я хочу   -  person user14845    schedule 07.03.2014


Ответы (2)


Расширяя мой комментарий к вопросу, довольно быстрый подход будет следующим, хотя с 40 000 строк вам придется немного подождать, я думаю:

unlist(lapply(seq_len(nrow(y)), function(i) min(sqrt(colSums((y[i, ] - t(x))^2)))))
#[1] 5.196152 5.385165 4.898979 4.898979 5.385165

И сравнительный бенчмаркинг:

x = matrix(runif(1e2*5), 1e2)
y = matrix(runif(1e2*5), 1e2)
library(microbenchmark)
alex = function() unlist(lapply(seq_len(nrow(y)), 
                           function(i) min(sqrt(colSums((y[i, ] - t(x))^2)))))
jlhoward = function() apply(y,1,function(y)
                                  min(apply(x,1,function(x,y)dist(rbind(x,y)),y)))
all.equal(alex(), jlhoward())
#[1] TRUE
microbenchmark(alex(), jlhoward(), times = 20)
#Unit: milliseconds
#       expr        min         lq     median         uq        max neval
#     alex()   3.369188   3.479011   3.600354   4.513114   4.789592    20
# jlhoward() 422.198621 431.565643 436.561057 442.643181 602.929742    20
person alexis_laz    schedule 07.03.2014

Попробуй это:

apply(y,1,function(y) min(apply(x,1,function(x,y)dist(rbind(x,y)),y)))
# [1] 5.196152 5.385165 4.898979 4.898979 5.385165

Работая изнутри наружу, мы связываем строку x со строкой y и вычисляем расстояние между ними с помощью функции dist(...) (написанной на C). Мы делаем это для заданной строки y с каждой строкой x по очереди, используя внутреннее apply(...), а затем находим минимум результата. Затем мы делаем это для каждой строки y во внешнем вызове apply(...).

person jlhoward    schedule 06.03.2014
comment
Большое вам спасибо .. он работал отлично, но работал очень долго ... Тем не менее спасибо за помощь. - person user14845; 10.03.2014