I have the following Pandas DataFrame:
In [31]:
import pandas as pd
sample = pd.DataFrame({'Sym1': ['a','a','a','d'],'Sym2':['a','c','b','b'],'Sym3':['a','c','b','d'],'Sym4':['b','b','b','a']},index=['Item1','Item2','Item3','Item4'])
In [32]: print(sample)
Out [32]:
Sym1 Sym2 Sym3 Sym4
Item1 a a a b
Item2 a c c b
Item3 a b b b
Item4 d b d a
and I want to find the elegant way to get the distance between each Item
according to this distance matrix:
In [34]:
DistMatrix = pd.DataFrame({'a': [0,0,0.67,1.34],'b':[0,0,0,0.67],'c':[0.67,0,0,0],'d':[1.34,0.67,0,0]},index=['a','b','c','d'])
print(DistMatrix)
Out[34]:
a b c d
a 0.00 0.00 0.67 1.34
b 0.00 0.00 0.00 0.67
c 0.67 0.00 0.00 0.00
d 1.34 0.67 0.00 0.00
For example comparing Item1
to Item2
would compare aaab
-> accb
-- using the distance matrix this would be 0+0.67+0.67+0=1.34
Ideal output:
Item1 Item2 Item3 Item4
Item1 0 1.34 0 2.68
Item2 1.34 0 0 1.34
Item3 0 0 0 2.01
Item4 2.68 1.34 2.01 0
this is doing twice as much work as needed, but technically works for non-symmetric distance matrices as well ( whatever that is supposed to mean )
you can make it more readable by writing it in pieces:
This is an old question, but there is a Scipy function that does this:
pdist
operates on Numpy matrices, andDataFrame.values
is the underlying Numpy NDarray representation of the data frame. Themetric
argument allows you to select one of several built-in distance metrics, or you can pass in any binary function to use a custom distance. It's very powerful and, in my experience, very fast. The result is a "flat" array that consists only of the upper triangle of the distance matrix (because it's symmetric), not including the diagonal (because it's always 0).squareform
then translates this flattened form into a full matrix.The docs have more info, including a mathematical rundown of the many built-in distance functions.
For a large data, I found a fast way to do this. Assume your data is already in np.array format, named as a.
Below is an experiment to compare the time needed for two approaches: