2

I have this 2d numpy array: [[0,2],[0,3],[0,1],[1,0]]. These elements represent points in x and y axes. So, for example, in [0,2] 0 is the x and 2 is the y.

I would like to get the point with the min x and min y. In this case, it would be [0,1]. I know I can easily do this with a for loop, but it takes too many resources. Is there a numpy function or something to calculate this?

1
  • numpy is also available on c++ and what I'm looking for is a numpy function so an answer written on c++ would be ok too. About your second question, yeah, that's why I have this this problem. [0,2], [0,3] and [0,1] has the min x but [0,1] is the only one with the min y. Commented Jun 3, 2016 at 9:11

2 Answers 2

4

You can first find the min of x, then find the min of y for pair where x equals the min of x:

np.min(xy[xy[:, 0] == np.min(xy[:, 0])], 0)
In [1]: xy
Out[1]: 
array([[0, 2],
       [0, 3],
       [0, 1],
       [1, 0]])

In [2]: np.min(xy[xy[:, 0] == np.min(xy[:, 0])], 0)
Out[2]: array([0, 1])

It is relatively fast, even for large array:

In [4]: timeit.timeit('np.min(xy[xy[:, 0] == np.min(xy[:, 0])], 0)',
                      'import numpy as np; xy = np.random.rand(100000, 2)', 
                      number = 100)
Out[4]: 0.06858562525758316

Old version which was a bit slower (before @OliverW. comment):

In [3]: timeit.timeit('np.min(xy[xy[:, 0] == np.min(xy, 0)[0]], 0)', 
                      'import numpy as np; xy = np.random.rand(100000, 2)', 
                      number = 100)
Out[3]: 0.20433111706540785
Sign up to request clarification or add additional context in comments.

3 Comments

Note that if efficiency is what you're going for (judging from your timing results, you are), you might just want to change np.min(xy, 0)[0] into np.min(xy[:,0]). That way you won't have to find the minimum of the "x-column" too, which is wasteful.
@OliverW. Thanks! I was more interested in the complexity which is linear in both case but your version divide the computation time by a factor of 3 which is great (I have updated the answer)!
Yeah, I was looking to get a better optimization instead of just using a for lop. The timing you get is more than enough.
3

You can use the NumPy built-in np.lexsort to do such a sorting, like so -

xy[np.lexsort(xy.T[::-1])[0]]

lexsort gets the sorted indices that respects such a precedence, but does so in the opposite sense, i.e. the last element, then the second last element and so on until the first element. So, we need to reverse the order of elements, that's why the appended [::-1]. Also, lexsort works along each column instead of each row as needed to solve our case, so we needed that transpose before reversing.

Sample run -

In [235]: xy
Out[235]: 
array([[0, 2],
       [0, 3],
       [0, 1],
       [1, 0]])

In [236]: xy[np.lexsort(xy.T[::-1])[0]]
Out[236]: array([0, 1])

1 Comment

Good edit, but I think there is a simple version of @Holt's answer, for this problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.