Numpy массив, как выбрать индексы, удовлетворяющие нескольким условиям? - PullRequest
117 голосов
/ 13 июня 2010

Предположим, у меня есть массив 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']

, но это не работает,Как бы я это сделал?

Ответы [ 6 ]

183 голосов
/ 13 июня 2010

Ваше выражение работает, если вы добавите скобки:

>>> y[(1 < x) & (x < 5)]
array(['o', 'o', 'a'], 
      dtype='|S1')
31 голосов
/ 05 сентября 2013

IMO OP на самом деле не хочет np.bitwise_and() (он же &) , но фактически хочет np.logical_and(), потому что они сравнивают логические значения, такие как True и False - см. этот пост SO логический против побитового , чтобы увидеть разницу.

>>> 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 примерно одинаковы.

19 голосов
/ 18 ноября 2014

Добавьте одну деталь к ответам @JF Себастьяна и @Mark Mikofski:
Если кто-то хочет получить соответствующие индексы (а не фактические значения массива), следующий код подойдет:

Дляудовлетворяющие множественным (всем) условиям:

select_indices = np.where( np.logical_and( x > 1, x < 5) )[0] #   1 < x <5

Для удовлетворения множественным (или) условиям:

select_indices = np.where( np.logical_or( x < 1, x > 5 ) )[0] # x <1 or x >5
5 голосов
/ 09 ноября 2017

Мне нравится использовать 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')

Преимущество состоит в том, что вы можете добавить еще много типов ограничений в векторизованную функцию.

Надеюсь, это поможет.

1 голос
/ 30 июня 2017

На самом деле я бы сделал это следующим образом:

L1 - индексный список элементов, удовлетворяющих условию 1; (возможно, вы можете использовать somelist.index(condition1) или np.where(condition1), чтобы получить L1.)

Точно так же вы получите L2, список элементов, удовлетворяющих условию 2;

Затем вы найдете пересечение, используя intersect(L1,L2).

Вы также можете найти пересечение нескольких списков, если вы получаете несколько условий дляудовлетворить.

Затем вы можете применить индекс в любом другом массиве, например, x.

0 голосов
/ 09 февраля 2019

Для 2D-массивов вы можете сделать это.Создайте 2D маску, используя условие.Введите в зависимости от массива маску условия в int или float и умножьте ее на исходный массив.

In [8]: arr
Out[8]: 
array([[ 1.,  2.,  3.,  4.,  5.],
       [ 6.,  7.,  8.,  9., 10.]])

In [9]: arr*(arr % 2 == 0).astype(np.int) 
Out[9]: 
array([[ 0.,  2.,  0.,  4.,  0.],
       [ 6.,  0.,  8.,  0., 10.]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...