1

As described here, if you want to find the closest value in a list for a number it can done as follows:

array = np.array([1,3,6,7,8])
value = 5
absolute_val_array = np.abs(array - value)
print(absolute_val_array)
smallest_difference_index = absolute_val_array.argmin()
closest_element = array[smallest_difference_index]
print(closest_element)

Which provides the right output:

[4 2 1 2 3]
6

Which would be the most appropiate way to convert at once a numpy array instead of a single value?

array = np.array([1,3,6,7,8])
values = [5,6,7,8,1,9,10]
absolute_val_array = np.abs(array - values)
print(absolute_val_array)
smallest_difference_index = absolute_val_array.argmin()
closest_element = array[smallest_difference_index]
print(closest_element)

Output:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-17-998d06731928> in <module>
      1 array = np.array([1,3,6,7,8])
      2 values = [5,6,7,8,1,9,10]
----> 3 absolute_val_array = np.abs(array - values)
      4 print(absolute_val_array)
      5 smallest_difference_index = absolute_val_array.argmin()

ValueError: operands could not be broadcast together with shapes (5,) (7,) 
M.E.
  • 4,955
  • 4
  • 49
  • 128
  • Please provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – ddejohn Jan 30 '22 at 21:25
  • Edited with a minimal reproducible example. – M.E. Jan 30 '22 at 21:36
  • Does this answer your question? [Vectorize finding closest value in an array for each element in another array](https://stackoverflow.com/q/20780017/90527) – outis Jan 31 '22 at 14:42

2 Answers2

1

Then you can go for outer subtraction:

>>> array[np.abs(np.subtract.outer(array, values)).argmin(axis=0)]
array([6, 6, 7, 8, 1, 8, 8])

i.e.,

>>> diffs = np.subtract.outer(array, values)

>>> diffs
array([[-4, -5, -6, -7,  0, -8, -9],
       [-2, -3, -4, -5,  2, -6, -7],
       [ 1,  0, -1, -2,  5, -3, -4],
       [ 2,  1,  0, -1,  6, -2, -3],
       [ 3,  2,  1,  0,  7, -1, -2]])

>>> abs_diffs = np.abs(diffs)

>>> closest_inds = abs_diffs.argmin(axis=0)
>>> closest_inds
array([2, 2, 3, 4, 0, 4, 4], dtype=int64)

>>> closest_elems = array[closest_inds]
array([6, 6, 7, 8, 1, 8, 8])

The major component diffs is conceputally formed as

for i, array_elem in enumerate(array):
    for j, values_elem in enumerate(values):
        diffs[i, j] = array_elem - values_elem
Mustafa Aydın
  • 17,645
  • 4
  • 15
  • 38
  • 1
    I chosed the answer using np.digitize as that is the one I finally implemented (at least for me it is easier to read), but I find this answer extremely useful and educational. Thanks – M.E. Jan 30 '22 at 22:58
1

Here's my first idea for a method:

a = numpy.random.random((3, 3))

vs = numpy.array([0.1, 0.4, 0.7])
ts = (vs[1:] + vs[:-1]) / 2
a_closest = vs[numpy.digitize(a, ts)]

Example values:

>>> a
array([[0.15070587, 0.62089681, 0.38381141],
       [0.89507882, 0.11427282, 0.17877406],
       [0.42782222, 0.27391192, 0.19966249]])
>>> vs[numpy.digitize(a, ts)]
array([[0.1, 0.7, 0.4],
       [0.7, 0.1, 0.1],
       [0.4, 0.4, 0.1]])

The basic concept is to use numpy.digitize to do binning.

Yann Vernier
  • 15,414
  • 2
  • 28
  • 26