Массив Numpy, как выбрать индексы, удовлетворяющие нескольким условиям?
предположим, что у меня есть массив numpy x = [5, 2, 3, 1, 4, 5],y = ['f', 'o', 'o', 'b', 'a', 'r']. Я хочу выбрать элементы в y соответствующих элементов x больше 1 и меньше 5.
пробовал
x = array([5, 2, 3, 1, 4, 5])
y = array(['f','o','o','b','a','r'])
output = y[x > 1 & x < 5] # desired output is ['o','o','a']
но это не сработает. Как бы я это сделал?
5 ответов:
ваше выражение работает, если добавить скобки:
>>> y[(1 < x) & (x < 5)] array(['o', 'o', 'a'], dtype='|S1')
IMO OP на самом деле не хочет
np.bitwise_and()(Он же&) но на самом деле хочетnp.logical_and()потому что они сравнивают логические значения, такие какTrueиFalse- смотрите этот пост на логические и побитовые чтобы увидеть разницу.>>> x = array([5, 2, 3, 1, 4, 5]) >>> y = array(['f','o','o','b','a','r']) >>> output = y[np.logical_and(x > 1, x < 5)] # desired output is ['o','o','a'] >>> output array(['o', 'o', 'a'], dtype='|S1')и эквивалентный способ сделать это с
np.all()установкаaxisсоответствующее аргумент.>>> output = y[np.all([x > 1, x < 5], axis=0)] # desired output is ['o','o','a'] >>> output array(['o', 'o', 'a'], dtype='|S1')по номера:
>>> %timeit (a < b) & (b < c) The slowest run took 32.97 times longer than the fastest. This could mean that an intermediate result is being cached. 100000 loops, best of 3: 1.15 µs per loop >>> %timeit np.logical_and(a < b, b < c) The slowest run took 32.59 times longer than the fastest. This could mean that an intermediate result is being cached. 1000000 loops, best of 3: 1.17 µs per loop >>> %timeit np.all([a < b, b < c], 0) The slowest run took 67.47 times longer than the fastest. This could mean that an intermediate result is being cached. 100000 loops, best of 3: 5.06 µs per loopиспользуя
np.all()медленнее, но&иlogical_andпримерно то же самое.
добавьте одну деталь к ответам @ J. F. Sebastian и @Mark Mikofski:
Если вы хотите получить соответствующие индексы (а не фактические значения массива), следующий код будет делать:для удовлетворения нескольких (всех) условия:
select_indices = np.where( np.logical_and( x > 1, x < 5) ) # 1 < x <5для удовлетворения нескольких (или) условия:
select_indices = np.where( np.logical_or( x < 1, x > 5 ) ) # x <1 or x >5
мне нравится использовать
np.vectorizeдля таких задач. Рассмотрим следующее:>>> # Arrays >>> x = np.array([5, 2, 3, 1, 4, 5]) >>> y = np.array(['f','o','o','b','a','r']) >>> # Function containing the constraints >>> func = np.vectorize(lambda t: t>1 and t<5) >>> # Call function on x >>> y[func(x)] >>> array(['o', 'o', 'a'], dtype='<U1')преимущество заключается в том, что вы можете добавить еще много типов ограничений в векторизованной функции.
надеюсь, что это помогает.
на самом деле я бы сделал это так:
L1-это индексный список элементов, удовлетворяющих условию 1; (Возможно, вы можете использовать
somelist.index(condition1)илиnp.where(condition1)чтобы получить L1.)аналогично, вы получаете L2, список элементов, удовлетворяющих условию 2;
тогда вы найдете пересечение с помощью
intersect(L1,L2).вы также можете найти пересечение нескольких списков, если вы получаете несколько условий для удовлетворения.
затем вы можете применить индекс в любом другом массиве, например, x.