2016-03-02 48 views
3

我使用以下鏈接來創建「歐幾里得相似矩陣」(即我轉換爲DataFrame)。 https://stats.stackexchange.com/questions/53068/euclidean-distance-score-and-similarity http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.spatial.distance.euclidean.html構造相似度矩陣的最有效方法

我做它的方式是其工作的一個迭代的方法,但它需要在數據集是大一會兒。 pandas pd.DataFrame.corr()對於皮爾森相關性非常快速且有用。

如何在不進行窮舉迭代的情況下執行歐式相似度量?

我天真下面的代碼:

#Euclidean Similarity 

#Create DataFrame 
DF_var = pd.DataFrame.from_dict({"s1":[1.2,3.4,10.2],"s2":[1.4,3.1,10.7],"s3":[2.1,3.7,11.3],"s4":[1.5,3.2,10.9]}).T 
DF_var.columns = ["g1","g2","g3"] 
#  g1 g2 g3 
# s1 1.2 3.4 10.2 
# s2 1.4 3.1 10.7 
# s3 2.1 3.7 11.3 
# s4 1.5 3.2 10.9 

#Create empty matrix to fill 
M_euclid = np.zeros((DF_var.shape[1],DF_var.shape[1])) 

#Iterate through DataFrame columns to measure euclidean distance 
for i in range(DF_var.shape[1]): 
    u = DF_var[DF_var.columns[i]] 
    for j in range(DF_var.shape[1]): 
     v = DF_var[DF_var.columns[j]] 
     #Euclidean distance -> Euclidean similarity 
     M_euclid[i,j] = (1/(1+sp.spatial.distance.euclidean(u,v))) 
DF_euclid = pd.DataFrame(M_euclid,columns=DF_var.columns,index=DF_var.columns) 

#   g1  g2  g3 
# g1 1.000000 0.215963 0.051408 
# g2 0.215963 1.000000 0.063021 
# g3 0.051408 0.063021 1.000000 

回答

5

有是scipy.spatial.distance中可以使用fo的兩個有用函數r:pdistsquareform。使用pdist將給出觀察值之間的成對距離作爲一維數組,並且squareform將把它轉換爲距離矩陣。

一個問題是,pdist默認使用距離度量,而不是相似度,所以您需要手動指定相似度函數。根據代碼中的註釋輸出來判斷,您的DataFrame也不在pdist預期的方向,所以我已經取消了您在代碼中執行的轉置。

import pandas as pd 
from scipy.spatial.distance import euclidean, pdist, squareform 


def similarity_func(u, v): 
    return 1/(1+euclidean(u,v)) 

DF_var = pd.DataFrame.from_dict({"s1":[1.2,3.4,10.2],"s2":[1.4,3.1,10.7],"s3":[2.1,3.7,11.3],"s4":[1.5,3.2,10.9]}) 
DF_var.index = ["g1","g2","g3"] 

dists = pdist(DF_var, similarity_func) 
DF_euclid = pd.DataFrame(squareform(dists), columns=DF_var.index, index=DF_var.index) 
+0

Hey @root,感謝您澄清使用pdist和squareform!爲什麼相似函數之後的對角矩陣爲0.0? –

+0

注意!對角線可以通過凱文在@ B.M的回答中的評論來解決。 –

1

你想scipy.spatial.distance.pdistsklearn.metrics.pairwise.pairwise_distances

1

我想你可以只使用pdistsquareform直接在數據幀廣播:

from scipy.spatial.distance import pdist,squareform 

In [6]: squareform(pdist(DF_var, metric='euclidean')) 

Out[6]: 
array([[ 0.  , 0.6164414 , 1.4525839 , 0.78740079], 
     [ 0.6164414 , 0.  , 1.1  , 0.24494897], 
     [ 1.4525839 , 1.1  , 0.  , 0.87749644], 
     [ 0.78740079, 0.24494897, 0.87749644, 0.  ]]) 
+1

移調第一:在[247]:1 /(1個+ squareform(pdist(DF_var.T))) 缺貨[247]: 陣列([[1,0.21596281,0.05140761], [ 0.21596281,1.,0.06302091], [0.05140761,0.06302091,1]]) –