0

I would like to sort (shortest to longest) an array 'a' (as given below) to the distance from the origin or a point (in my case 0,0) and store it to a similar array type 'b' or replacing the array 'a'

the below given points are 3d numpy array

[[[  510.    11.]]

 [[  651.   276.]]

 [[  269.    70.]]

 [[  920.    26.]]

 [[  513.    21.]]

 [[ 1197.   620.]]

 [[  407.   268.]]

 [[  452.    35.]]

 [[  435.     3.]]

 [[  520.    20.]]

 [[ 1151.   499.]]

 [[  104.    26.]]

 [[  754.    28.]]

 [[  263.   111.]]

 [[  731.    12.]]

 [[  972.   200.]]

 [[ 1186.   614.]]

 [[  437.     2.]]

 [[ 1096.    68.]]

 [[  997.   201.]]

 [[ 1087.   200.]]

 [[  913.   201.]]

 [[ 1156.   510.]]

 [[  994.   230.]]

 [[  793.    29.]]

 [[  514.    19.]]]

I cannot find any helpful information regarding these kind of 3d np arrays sorting

ps: These points 'a' were obtained from Goodfeaturestotrack ,OPEN CV ,python 3.6

and how do you clear an array to Null type ?

 #this is  clustering algorithm    
    for index in range(len(a): #a is the above matrix 3d np array
#find distance was already defined and is euclidean distance formula
            if findDistance(a[index][0], a[index][1], a[index + 1][0], a[index + 1][1]) < 3: #calculation euclidean distance between ai and ai+1
                c.append(index)
            if findDistance(a[index][0], a[index][1], a[index + 1][0], a[index + 1][1]) > 3: #calculation euclidean distance between ai and ai+1
                if len(c) > 10:
                    cp = np.insert(cp, c, 0)

                    c = [] # should clear c **is this correct ??**

3 Answers3

1

I like to keep this handy to calculate distances in several array formats... it isn't a one-liner, but it works. Details on its implementations can be found elsewhere on stack by searching for 'einsum' and numpy as keywords. Import numpy as np required, this is just the def and you need 2 arrays

import numpy as np

def e_dist(a, b, metric='euclidean'):

"""Distance calculation for 1D, 2D and 3D points using einsum
: a, b   - list, tuple, array in 1,2 or 3D form
: metric - euclidean ('e','eu'...), sqeuclidean ('s','sq'...),
:-----------------------------------------------------------------------
"""
a = np.asarray(a)
b = np.atleast_2d(b)
a_dim = a.ndim
b_dim = b.ndim
if a_dim == 1:
    a = a.reshape(1, 1, a.shape[0])
if a_dim >= 2:
    a = a.reshape(np.prod(a.shape[:-1]), 1, a.shape[-1])
if b_dim > 2:
    b = b.reshape(np.prod(b.shape[:-1]), b.shape[-1])
diff = a - b
dist_arr = np.einsum('ijk,ijk->ij', diff, diff)
if metric[:1] == 'e':
    dist_arr = np.sqrt(dist_arr)
dist_arr = np.squeeze(dist_arr)
return dist_arr

Then you can sort the result if needed, for example

a = np.random.randint(0, 10, size=(10,2))

orig = np.array([0,0])

    e_dist(a, orig)

    array([  4.12,   9.9 ,   7.07,   6.08,   3.16,  10.63,   8.54,   7.28,   7.21,
             6.08])
    np.sort(e_dist(a, orig))

    array([  3.16,   4.12,   6.08,   6.08,   7.07,   7.21,   7.28,   8.54,   9.9 ,
            10.63])

ADDENDUM

I should have added that you can get the sorted values using argsort as exemplified below

np.argsort(e_dist(a, orig))
array([4, 0, 3, 9, 2, 8, 7, 6, 1, 5], dtype=int64)

idx = np.argsort(art.e_dist(a, orig))

closest = a[idx]
array([[3, 1],
       [1, 4],
       [1, 6],
       [6, 1],
       [5, 5],
       [4, 6],
       [2, 7],
       [8, 3],
       [7, 7],
       [7, 8]])
NaN
  • 2,212
  • 2
  • 18
  • 23
  • I will get back to u once I implement this in my code ! thanks ! – Tauseef Ahmed Taz Oct 05 '17 at 06:01
  • works like a charm ! ! guess there is a mistake `np.argsort(art.e_dist(a, orig))` must be `np.argsort(e_dist(a, orig))` is it so?? `art` is it an array name? – Tauseef Ahmed Taz Oct 05 '17 at 14:12
  • sorry... art is from my arraytool module... I forgot to remove it since I imported the e_dist from there. If you are including e_dist in your own script, then you don't need the 'art' portion – NaN Oct 05 '17 at 15:58
  • Yes I did remove it ! This code is much **faster** than the code mentioned by Mr Beasley. Thanks ! – Tauseef Ahmed Taz Oct 05 '17 at 16:05
0
def distance_squared(x1,y1,x2,y2):
    return (x1-x2)**2 + (y1-y2)**2
target_point = 0,0
sorted(a,key=lambda point:distance_squared(target_point[0],target_point[1],*point[0]))
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
  • how to obtain the sorted array ? if i assign`b=sorted(a,key=lambda point:distance_squared(target_point[0],target_point[1],*point[0]))` and `print ( 'sorted',b)` I get `sorted [array([[ 250., 92.]], dtype=float32), array([[ 269., 70.]], dtype=float32), array([[ 407., 268.]], dtype=.....` how can i get a similar array like then one above but sorted – Tauseef Ahmed Taz Oct 04 '17 at 18:50
  • try numpy.array(b) – Matthew Ciaramitaro Oct 04 '17 at 19:09
0

You can use scikit-learn's built-in pairwise-distance function.


from sklearn.metrics.pairwise import pairwise_distances
d = pairwise_distances(X, Y, metric="euclidean")
YScharf
  • 1,638
  • 15
  • 20