'Find the first and last element of a NumPy array larger than a threshold

I need to find the first and the last element of a numpy.ndarray which are above a specified threshold. I found the following solution, which works, but it looks a bit convoluted. Is there a simpler/more Pythonic way?

import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1)

test = np.random.uniform(0, 1, 100)
above_threshold = test > 0.95
plt.plot(above_threshold)

indices = np.nonzero(above_threshold)
imin = np.min(indices)
imax = np.max(indices)

print(imin, imax)


Solution 1:[1]

You could just access the first/last elements

s = np.flatnonzero(test > 0.95)
imin, imax = s[0], s[-1]

Solution 2:[2]

A fancy index on the first element of the tuple returned by nonzero is all you need:

imin, imax = np.nonzero(above_threshold)[0][[0,-1]]

In [465]: imin
Out[465]: 21

In [466]: imax
Out[466]: 87

Output of the above using this sample:

In [454]: test
Out[454]:
array([4.17022005e-01, 7.20324493e-01, 1.14374817e-04, 3.02332573e-01,
       1.46755891e-01, 9.23385948e-02, 1.86260211e-01, 3.45560727e-01,
       3.96767474e-01, 5.38816734e-01, 4.19194514e-01, 6.85219500e-01,
       2.04452250e-01, 8.78117436e-01, 2.73875932e-02, 6.70467510e-01,
       4.17304802e-01, 5.58689828e-01, 1.40386939e-01, 1.98101489e-01,
       8.00744569e-01, 9.68261576e-01, 3.13424178e-01, 6.92322616e-01,
       8.76389152e-01, 8.94606664e-01, 8.50442114e-02, 3.90547832e-02,
       1.69830420e-01, 8.78142503e-01, 9.83468338e-02, 4.21107625e-01,
       9.57889530e-01, 5.33165285e-01, 6.91877114e-01, 3.15515631e-01,
       6.86500928e-01, 8.34625672e-01, 1.82882773e-02, 7.50144315e-01,
       9.88861089e-01, 7.48165654e-01, 2.80443992e-01, 7.89279328e-01,
       1.03226007e-01, 4.47893526e-01, 9.08595503e-01, 2.93614148e-01,
       2.87775339e-01, 1.30028572e-01, 1.93669579e-02, 6.78835533e-01,
       2.11628116e-01, 2.65546659e-01, 4.91573159e-01, 5.33625451e-02,
       5.74117605e-01, 1.46728575e-01, 5.89305537e-01, 6.99758360e-01,
       1.02334429e-01, 4.14055988e-01, 6.94400158e-01, 4.14179270e-01,
       4.99534589e-02, 5.35896406e-01, 6.63794645e-01, 5.14889112e-01,
       9.44594756e-01, 5.86555041e-01, 9.03401915e-01, 1.37474704e-01,
       1.39276347e-01, 8.07391289e-01, 3.97676837e-01, 1.65354197e-01,
       9.27508580e-01, 3.47765860e-01, 7.50812103e-01, 7.25997985e-01,
       8.83306091e-01, 6.23672207e-01, 7.50942434e-01, 3.48898342e-01,
       2.69927892e-01, 8.95886218e-01, 4.28091190e-01, 9.64840047e-01,
       6.63441498e-01, 6.21695720e-01, 1.14745973e-01, 9.49489259e-01,
       4.49912133e-01, 5.78389614e-01, 4.08136803e-01, 2.37026980e-01,
       9.03379521e-01, 5.73679487e-01, 2.87032703e-03, 6.17144914e-01])

Solution 3:[3]

Returns 21 and 87.

import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1)

test = np.random.uniform(0, 1, 100)
imin, imax = np.ma.flatnotmasked_edges(np.ma.masked_array(test, test <= 0.95))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 rafaelc
Solution 2 Peter Mortensen
Solution 3