2016-03-02 6 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() действительно быстр и полезен для коррекций pearson.

Как я могу выполнить меру евклидовой подобия без исчерпывающей итерации?

Мой наивный код ниже:

#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 это: pdist и squareform. Использование 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

Эй, @root, спасибо за разъяснение использования pdist и squareform! Почему диагональная матрица 0,0 после функции подобия? –

+0

Примечание! Диагональ может быть исправлена ​​с комментарием в ответе Кевина от @ B.M. –

1

Вы хотите scipy.spatial.distance.pdist или sklearn.metrics.pairwise.pairwise_distances

1

Я думаю, вы можете просто использовать pdist и squareform вещать прямо на DataFrame:

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.]]) –

Смежные вопросы