2013-05-10 36 views
3

我寫了一個簡短的'for'循環來查找數據框中的每一行與所有其他行之間的最小歐幾里得距離(並記錄排最近)。理論上這避免了與嘗試計算非常大的矩陣的距離測量值相關的誤差。然而,雖然沒有太多的東西被保存在內存中,但對於大型矩陣非常緩慢(我的約150K行的使用案例仍在運行)。如何計算大數據幀的歐幾里得距離(僅保存彙總)

我想知道是否有人可以建議或指引我在正確的方向上矢量化我的功能,使用應用程序或類似的方面。對於看似簡單的問題表示歉意,但我仍在努力以矢量化的方式進行思考。

在此先感謝(和耐心等待)。

require(proxy) 

df<-data.frame(matrix(runif(10*10),nrow=10,ncol=10), row.names=paste("site",seq(1:10))) 

min.dist<-function(df) { 
#df for results 
all.min.dist<-data.frame() 
#set up for loop 
for(k in 1:nrow(df)) { 
    #calcuate dissimilarity between each row and all other rows 
    df.dist<-dist(df[k,],df[-k,]) 
    # find minimum distance 
    min.dist<-min(df.dist) 
    # get rowname for minimum distance (id of nearest point) 
    closest.row<-row.names(df)[-k][which.min(df.dist)] 
    #combine outputs 
    all.min.dist<-rbind(all.min.dist,data.frame(orig_row=row.names(df)[k], 
    dist=min.dist, closest_row=closest.row)) 
    } 
#return results 
return(all.min.dist) 
         } 
#example 
min.dist(df) 
+0

我沒有資格對矢量化進行評論,但是通過查找距離平方的最小值可以獲得一些好處,然後僅在返回時取平方根。 – 2013-05-10 02:26:00

+0

你有檢查http://stackoverflow.com/questions/3029639/calculating-all-distances-between-one-point-and-a-group-of-points-efficiently-in?rq=1? – 2013-05-10 02:29:00

+0

循環內的all.min.dist < - rbind(all.min.dist,...)非常糟糕,因爲它在每次迭代中創建一個更大的對象。閱讀*預先分配*。 – flodel 2013-05-10 02:33:28

回答

3

這應該是一個好的開始。它使用快速矩陣操作並避免了越來越多的對象構造,這兩個建議都在評論中提出。

min.dist <- function(df) { 

    which.closest <- function(k, df) { 
    d <- colSums((df[, -k] - df[, k])^2) 
    m <- which.min(d) 
    data.frame(orig_row = row.names(df)[k], 
       dist  = sqrt(d[m]), 
       closest_row = row.names(df)[-k][m]) 
    } 

    do.call(rbind, lapply(1:nrow(df), which.closest, t(as.matrix(df)))) 
} 

如果這仍然太慢,作爲建議的改進,你可以在一個時間,而不是單一的一個計算爲ķ點的距離。需要在速度和內存使用量之間進行折衷。

編輯:而且讀https://stackoverflow.com/a/16670220/1201032

+0

謝謝flodel,這既是矢量化,也是直接計算歐幾里得距離的直接事實。它仍然相當緩慢,因此可能一次探索計算多個點。 – nickb 2013-05-10 06:25:03

0

通常,內置函數是快於自己編碼它(因爲用Fortran或C/C++編碼和優化)。

看來,函數DIST {統計}答案對您的問題點:

說明 此函數計算,並返回通過使用指定的距離度量以計算數據的行之間的距離計算的距離矩陣矩陣。

+1

OP說他的用例是一個有150k行的矩陣。 'dist'會嘗試返回一個150k-by-150k的完整矩陣並且阻塞...另外OP不關心那麼多的數據,他只想要每個點的最近點。因此,一次一行的方法更加節省內存。 – flodel 2013-05-10 03:21:57