Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

find two closest values in numpy ndarray

i have a numpy ndarray which looks like this

np.array(
[[40.26164428, 63.50590524, 58.30951895],
 [50.99019514, 69.0651866 , 60.44005295],
 [20.24845673, 14.31782106, 58.52349955],
 [54.58937626, 53.03772242, 21.09502311],
 [56.75385449, 57.5847202 ,  1.41421356]])

(NOTE: the arrays i generate are always in different shapes ( the shape of this array is (5, 3) but it can be (2, 2) (4, 1)... ), so this isn't a 3D coordinates array, it just generated like that)

What i need is to find the two closest values of the generated array and return their indices, in this case the values are 58.30951895 and 58.52349955, which should return the coordinates [0, 2] and [2, 2]

I've tried to use cKDtree but this isn't a coordinate array so that doesn't work in this case, how should i do this?

like image 318
baronsec Avatar asked Mar 03 '26 19:03

baronsec


2 Answers

I'm going to be embarrassed when someone points out a one-liner, but here's a way to do it.

I flatten the array, then sort it, then find the deltas between each element. Find the minimum delta. Now, from the sorted array, I know the values of the two closest elements. argwhere then gives me the coordinates.

import numpy as np

data = np.array(
[[40.26164428, 63.50590524, 58.30951895],
 [50.99019514, 69.0651866 , 60.44005295],
 [20.24845673, 14.31782106, 58.52349955],
 [54.58937626, 53.03772242, 21.09502311],
 [56.75385449, 57.5847202 ,  1.41421356]])


order = np.sort(data.reshape(-1))
delta = np.diff(order)
am = np.argmin(delta)
print( np.argwhere(data == order[am]))
print( np.argwhere(data == order[am+1]))

Output:

C:\tmp>python x.py
[[0 2]]
[[2 2]]
like image 116
Tim Roberts Avatar answered Mar 05 '26 09:03

Tim Roberts


If I understand it correctly their position in the array is irrelevant, so in that case is simple, put the numbers in a list in a way that it remember their original position, then sorted it and find the lowest difference between two consecutive elements

>>> import itertools
>>> def pairwise(iterable):
        a,b = itertools.tee(iterable)
        next(b,None)
        return zip(a,b)

>>> data=[[40.26164428, 63.50590524, 58.30951895],
 [50.99019514, 69.0651866,  60.44005295],
 [20.24845673, 14.31782106, 58.52349955],
 [54.58937626, 53.03772242, 21.09502311],
 [56.75385449, 57.5847202,   1.41421356]]
>>> linear=[ (value,x,y) for x,row in enumerate(data) for y,value in enumerate(row)]
>>> linear.sort(key=lambda x:x[0])
>>> min(pairwise(linear),key=lambda pair: abs(pair[0][0]-pair[1][0]))
((58.30951895, 0, 2), (58.52349955, 2, 2))
>>> 
like image 20
Copperfield Avatar answered Mar 05 '26 07:03

Copperfield



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!