Проверьте, находится ли каждый элемент в массиве numpy в отдельном списке

#python #arrays #numpy #vectorization

#python #массивы #numpy #векторизация

Вопрос:

Я хотел бы сделать что-то вроде этого:

 >>> y = np.arange(5)
>>> y in (0, 1, 2)
array([True, True, True, False, False])
  

Этот синтаксис не работает. Каков наилучший способ достичь желаемого результата?

(Я ищу общее решение. Очевидно, что в этом конкретном случае я мог бы сделать y < 3 .)

Я объясню это немного более четко для вас, ребята, поскольку, по крайней мере, несколько человек, похоже, сбиты с толку.

Вот долгий способ добиться желаемого поведения:

 new_y = np.empty_like(y)
for i in range(len(y)):
    if y[i] in (0, 1, 2):
        new_y[i] = True
    else:
        new_y[i] = False
  

Я ищу такое поведение в более компактной форме.

Вот другое решение:

 new_y = np.array([True if item in (0, 1, 2) else False for item in y])
  

Опять же, просто ищу более простой способ.

Комментарии:

1. np.in1d(y, [0,1,2])

Ответ №1:

Хорошим инструментом общего назначения является широковещательное, или «внешнее», сравнение элементов двух массивов:

 In [35]: y=np.arange(5)                                                         
In [36]: x=np.array([0,1,2])                                                    
In [37]: y[:,None]==x                                                           
Out[37]: 
array([[ True, False, False],
       [False,  True, False],
       [False, False,  True],
       [False, False, False],
       [False, False, False]])
  

Это выполняет быстрое сравнение между каждым элементом y и каждым элементом x . В зависимости от ваших потребностей, вы можете сконденсировать этот массив вдоль одной из осей:

 In [38]: (y[:,None]==x).any(axis=1)                                             
Out[38]: array([ True,  True,  True, False, False])
  

Предложен комментарий in1d . Я думаю, что неплохо бы взглянуть на его код. У него есть несколько стратегий в зависимости от относительных размеров входных данных.

 In [40]: np.in1d(y,x)                                                           
Out[40]: array([ True,  True,  True, False, False])
In [41]: np.array([True if item in x else False for item in y])                 
Out[41]: array([ True,  True,  True, False, False])
  

Самый быстрый может зависеть от размера входных данных. Начальные списки ваше понимание списка может быть быстрее. Эта версия с чистым списком, безусловно, самая быстрая:

 [True if item in (0,1,2) else False for item in (0,1,2,3,4)] 
[item in (0,1,2) for item in (0,1,2,3,4)]    # simpler
  

Комментарии:

1. Если кто-нибудь еще окажется здесь позже и увидит комментарий np.in1d, вероятно, лучше проверить np.isin как современного преемника: numpy.org/doc/stable/reference/generated /…

2. @Starman, но посмотрите на его код

3. Я посмотрел на код, и np.isin кажется, что он просто вызывает np.in1d под капотом? github.com/numpy/numpy/blob/v1.24.0/numpy/lib/… Также np.in1d документы рекомендуют использовать np.isin .