3

I used to use min([a, b], key=lambda x:abs(x-x0)) to find which of a and b are the closest to x0.

a = 1
b = 2
x0 = 1.49
print(min([a, b], key=lambda x:abs(x-x0)))
# >>> 1

Now, a and b are numpy arrays with an arbitrary number of dimensions. I would like to build an array composed of the closest values to x0 between both arrays, element by element.

import numpy as np

a = np.array([[1, 2], [3, 5]])
b = np.array([[6, 2], [6, 2]])

## case 1
x0 = 4
# >>> should return np.array([[6, 2], [3, 5]])

## case 2
x0 = np.array([[1, 2], [3, 4]])
# >>> should return np.array([[1, 2], [3, 5]])

To find the elementwise minimum between two arrays, we can use numpy.minimum. Unfortunately, it does not take lambda functions as arguments.

How should I do ?

Liris
  • 1,399
  • 3
  • 11
  • 29
  • `arbitrary number of dimensions` is somewhat arbitrary. Are their dimensions equal, and how do they relate to the dimension of `x0`? Do you have a sample in hand? – Quang Hoang Oct 28 '20 at 16:39
  • In my case, `x0` is a single float. The dimensions of `a` and `b` should not play in this problem, as soon as `a.shape == b.shape`, right ? – Liris Oct 28 '20 at 16:41
  • Can you add [mcve]? – Divakar Oct 28 '20 at 16:45

2 Answers2

1

Is this what you are looking for?

np.where(np.abs(a - x0) < np.abs(b - x0), a, b)
Marat
  • 15,215
  • 2
  • 39
  • 48
  • I think there is a mistake: `np.abs(a - x0) < np.abs(a - x0)` should be `np.abs(a - x0) < np.abs(b - x0)` right ? – Liris Oct 28 '20 at 16:55
  • This works only for two points `a` and `b` and my solution works for any list of points. – mathfux Oct 28 '20 at 18:19
0

numpy doesn't support a key function. A possible fix is storing distances in a separate array and determining index of smallest distance with np.argmin. An example with 4D points:

points = np.array([[0, 0.1, 0.2, 0.3], [3, 4, 5, 5], [6, 4.5, 1, 1]])
x0 = [3, 0.5, 5, 5]
distances = np.sum((points - x0)**2, axis=1)
output = points[np.argmin(distances)]

Output:

array([3., 4., 5., 5.])
mathfux
  • 5,759
  • 1
  • 14
  • 34