Массив 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.