Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficiently Calculating a Euclidean Distance Matrix Using Numpy

Tags:

I have a set of points in 2-dimensional space and need to calculate the distance from each point to each other point.

I have a relatively small number of points, maybe at most 100. But since I need to do it often and rapidly in order to determine the relationships between these moving points, and since I'm aware that iterating through the points could be as bad as O(n^2) complexity, I'm looking for ways to take advantage of numpy's matrix magic (or scipy).

As it stands in my code, the coordinates of each object are stored in its class. However, I could also update them in a numpy array when I update the class coordinate.

class Cell(object):     """Represents one object in the field."""     def __init__(self,id,x=0,y=0):         self.m_id = id         self.m_x = x         self.m_y = y 

It occurs to me to create a Euclidean distance matrix to prevent duplication, but perhaps you have a cleverer data structure.

I'm open to pointers to nifty algorithms as well.

Also, I note that there are similar questions dealing with Euclidean distance and numpy but didn't find any that directly address this question of efficiently populating a full distance matrix.

like image 948
Wes Modes Avatar asked Mar 28 '14 18:03

Wes Modes


People also ask

How do you measure Euclidean distance in Python?

dist() method in Python is used to the Euclidean distance between two points p and q, each given as a sequence (or iterable) of coordinates. The two points must have the same dimension. This method is new in Python version 3.8. Returns: the calculated Euclidean distance between the given points.

How do you find the distance of a matrix in python?

A distance matrix contains the distances computed pairwise between the vectors of matrix/ matrices. scipy. spatial package provides us distance_matrix() method to compute the distance matrix. Generally matrices are in the form of 2-D array and the vectors of the matrix are matrix rows ( 1-D array).


Video Answer


2 Answers

You can take advantage of the complex type :

# build a complex array of your cells z = np.array([complex(c.m_x, c.m_y) for c in cells]) 

First solution

# mesh this array so that you will have all combinations m, n = np.meshgrid(z, z) # get the distance via the norm out = abs(m-n) 

Second solution

Meshing is the main idea. But numpy is clever, so you don't have to generate m & n. Just compute the difference using a transposed version of z. The mesh is done automatically :

out = abs(z[..., np.newaxis] - z) 

Third solution

And if z is directly set as a 2-dimensional array, you can use z.T instead of the weird z[..., np.newaxis]. So finally, your code will look like this :

z = np.array([[complex(c.m_x, c.m_y) for c in cells]]) # notice the [[ ... ]] out = abs(z.T-z) 

Example

>>> z = np.array([[0.+0.j, 2.+1.j, -1.+4.j]]) >>> abs(z.T-z) array([[ 0.        ,  2.23606798,  4.12310563],        [ 2.23606798,  0.        ,  4.24264069],        [ 4.12310563,  4.24264069,  0.        ]]) 

As a complement, you may want to remove duplicates afterwards, taking the upper triangle :

>>> np.triu(out) array([[ 0.        ,  2.23606798,  4.12310563],        [ 0.        ,  0.        ,  4.24264069],        [ 0.        ,  0.        ,  0.        ]]) 

Some benchmarks

>>> timeit.timeit('abs(z.T-z)', setup='import numpy as np;z = np.array([[0.+0.j, 2.+1.j, -1.+4.j]])') 4.645645342274779 >>> timeit.timeit('abs(z[..., np.newaxis] - z)', setup='import numpy as np;z = np.array([0.+0.j, 2.+1.j, -1.+4.j])') 5.049334864854522 >>> timeit.timeit('m, n = np.meshgrid(z, z); abs(m-n)', setup='import numpy as np;z = np.array([0.+0.j, 2.+1.j, -1.+4.j])') 22.489568296184686 
like image 102
Kiwi Avatar answered Sep 28 '22 05:09

Kiwi


If you don't need the full distance matrix, you will be better off using kd-tree. Consider scipy.spatial.cKDTree or sklearn.neighbors.KDTree. This is because a kd-tree kan find k-nearnest neighbors in O(n log n) time, and therefore you avoid the O(n**2) complexity of computing all n by n distances.

like image 45
Sturla Molden Avatar answered Sep 28 '22 03:09

Sturla Molden