4

Given a threshold alpha and a numpy array a, there are multiple possibilities for finding the first index i such that arr[i] > alpha; see Numpy first occurrence of value greater than existing value:

numpy.searchsorted(a, alpha)+1
numpy.argmax(a > alpha)

In my case, alpha can be either a scalar or an array of arbitrary shape. I'd like to have a function get_lowest that works in both cases:

alpha = 1.12
arr = numpy.array([0.0, 1.1, 1.2, 3.0])
get_lowest(arr, alpha)  # 2

alpha = numpy.array(1.12, -0.5, 2.7])
arr = numpy.array([0.0, 1.1, 1.2, 3.0])
get_lowest(arr, alpha)  # [2, 0, 3]

Any hints?

3
  • Just to clarify: arr is always 1d and sorted? And you treat the elements of alpha independently? What's the relative size of arr and alpha? A simple iteration on alpha might be the fastest, especially if searchsorted is the optimal tool for a single value. Commented Jan 21, 2018 at 18:03
  • @hpaulj alpha can be an array of arbitrary shape, and is typically much larger than arr. Commented Jan 21, 2018 at 21:02
  • I'm reminded of a padding problem - with variable length lists. @Divakar's style of solution might be useful, stackoverflow.com/questions/43924187/… Commented Jan 21, 2018 at 21:08

2 Answers 2

2

You can use broadcasting:

In [9]: arr = array([ 0. ,  1.1,  1.2,  3. ])
In [10]: alpha = array([ 1.12, -0.5 ,  2.7 ])
In [11]: np.argmax(arr > np.atleast_2d(alpha).T, axis=1)
Out[11]: array([2, 0, 3])

To collapse multidimensional arrays, you can use np.squeeze, but you might have to do something special if you want a Python float in your first case:

def get_lowest(arr, alpha):
    b = np.argmax(arr > np.atleast_2d(alpha).T, axis=1)
    b = np.squeeze(b)
    if np.size(b) == 1:
        return float(b)
    return b
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer! Unfortunately, this returns an array (of shape 1,1) if the input is a float. I need a float.
Easily fixed @NicoSchlömer, no?
2

searchsorted actually does the trick:

np.searchsorted(a, alpha)

The axis argument to argmax helps out; this

np.argmax(numpy.add.outer(alpha, -a) < 0, axis=-1)

does the trick. Indeed

import numpy as np

a = np.array([0.0, 1.1, 1.2, 3.0])

alpha = 1.12
    
np.argmax(np.add.outer(alpha, -a) < 0, axis=-1)  # 0
np.searchsorted(a, alpha)  # 0

alpha = np.array([1.12, -0.5, 2.7])
np.argmax(np.add.outer(alpha, -a) < 0, axis=-1)  # [2 0 3]
np.searchsorted(a, alpha)  # [2 0 3]

1 Comment

searchsorted didn't work for me - but the argmax / outer route did. Probably because not sorted :\

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.