use*_*845 8 loops for-loop r euclidean-distance
我需要生成一个数据帧,其中数据帧的每一行与另一个数据帧的所有其他行之间的欧几里德距离最小.我的数据帧很大(大约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)))
}
Run Code Online (Sandbox Code Playgroud)
但这只适用于i = j.我基本上需要的是通过逐行循环每一行来找到最小的欧氏距离(y [1,1:7],然后是y [2,1:7],依此类推直到i = 5)"y"数据帧与"x"数据帧的所有行(x [i,1:7]).每次这样做,我需要它来找到每个计算的最小欧几里德距离y数据帧的第i行和x数据帧的所有行,并将其存储在另一个数据帧中.
试试这个:
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
Run Code Online (Sandbox Code Playgroud)
从内到外,我们将一行x绑定到y行,并使用dist(...)函数计算它们之间的距离(用C语言编写).我们对y的给定行执行此操作,依次使用x,每行x apply(...),然后查找结果的最小值.然后我们对外部调用中的每一行y执行此操作apply(...).
扩展我对这个问题的评论,一个相当快速的方法如下,尽管我猜有 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
Run Code Online (Sandbox Code Playgroud)
以及比较基准测试:
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
Run Code Online (Sandbox Code Playgroud)