Одним из способов достижения желаемого результата является использование лямбда-функции с np.vectorize
:
>>> a = np.array([1, 2, None, 4, -1])
>>> f = np.vectorize(lambda t: t and t>0)
>>> np.where(f(a))
(array([0, 1, 3], dtype=int64),)
Конечно, если массив не содержит отрицательных целых чисел, вы можете просто использовать np.where(a)
, поскольку и None
, и 0
оцениваются как False
:
>>> a = np.array([1, 2, None, 4, 0])
>>> np.where(a)
(array([0, 1, 3], dtype=int64),)
Еще один способ решить эту проблему - сначала преобразовать массив в тип float dtype, который имеет эффект преобразования None
до np.nan
. Тогда np.where(a>0)
можно использовать как обычно.
>>> a = np.array([1, 2, None, 4, -1])
>>> np.where(a.astype(float) > 0)
(array([0, 1, 3], dtype=int64),)
Сравнение времени:
![enter image description here](https://i.stack.imgur.com/o9G2P.png)
Так Подход Боба, хотя и не такой легкий для глаз, примерно в два раза быстрее, чем подход np.vectorise
, и немного медленнее, чем подход с плавающим преобразованием.
Код для воспроизведения:
import perfplot
import numpy as np
f = np.vectorize(lambda t: t and t>0)
choices = list(range(-10,11)) + [None]
def cdjb(arr):
return np.where(f(arr))
def cdjb2(arr):
return np.where(arr.astype(float) > 0)
def Bob(arr):
deep_copy = np.copy(arr)
deep_copy[deep_copy == None] = 0
return (deep_copy > 0).nonzero()[0]
perfplot.show(
setup=lambda n: np.random.choice(choices, size=n),
n_range=[2**k for k in range(25)],
kernels=[
cdjb, cdjb2, Bob
],
xlabel='len(a)',
)