2015-09-09 3 views
4

Для каждого элемента в массиве A[:,3:], который также находится в массиве B, я хочу, чтобы установить значение 0, которое создает массив resultПересечение 2d и 1d Numpy массива

import numpy as np 

A = np.array([[1, 1, 10, 101, 102, 103, 0, 0], 
       [2, 2, 10, 102, 108, 0, 0, 0], 
       [3, 3, 11, 101, 102, 106, 107, 108]]) 

B = np.array([101, 106, 108]) 

result = np.array([[1, 1, 10, 0, 102, 103, 0, 0], 
        [2, 2, 10, 102, 0, 0, 0, 0], 
        [3, 3, 11, 0, 102, 0, 107, 0]]) 

Я знаю, что есть способ для этого используйте in1d и трансляцию A как 1D-массив, но я понятия не имею, как это сделать.

Любая помощь была бы принята с благодарностью.

ответ

6

Если вы подаете в этом нарезанной 2D массива A[:,3:] к np.in1d, было бы расплющить его в 1D массив и сравнить с B вхождений и, таким образом, создать 1D маску, которая может быть преобразована и используется для булевой индексации в этом нарезанной массив для установки TRUE элементов на zeros. Реализация один лайнер будет выглядеть примерно так -

A[:,3:][np.in1d(A[:,3:],B).reshape(A.shape[0],-1)] = 0 

Пример запуска -

In [37]: A 
Out[37]: 
array([[ 1, 1, 10, 101, 102, 103, 0, 0], 
     [ 2, 2, 10, 102, 108, 0, 0, 0], 
     [ 3, 3, 11, 101, 102, 106, 107, 108]]) 

In [38]: np.in1d(A[:,3:],B) # Flattened mask 
Out[38]: 
array([ True, False, False, False, False, False, True, False, False, 
     False, True, False, True, False, True], dtype=bool) 

In [39]: np.in1d(A[:,3:],B).reshape(A.shape[0],-1) # Reshaped mask 
Out[39]: 
array([[ True, False, False, False, False], 
     [False, True, False, False, False], 
     [ True, False, True, False, True]], dtype=bool) 

In [40]: A[:,3:][np.in1d(A[:,3:],B).reshape(A.shape[0],-1)] = 0 # Final code 

In [41]: A 
Out[41]: 
array([[ 1, 1, 10, 0, 102, 103, 0, 0], 
     [ 2, 2, 10, 102, 0, 0, 0, 0], 
     [ 3, 3, 11, 0, 102, 0, 107, 0]]) 

Чтобы сделать вещи проще, вы можете создать вид уплощенной A и использовать маску 1D полученный от np.in1d, чтобы иметь более элегантное решение. Для решения, которое изменяет только нарезанные A[:,3:], вы можете использовать .flat, а затем индекс, как так -

A[:,3:].flat[np.in1d(A[:,3:],B)] = 0 

Для случая, когда вы хотели бы установить соответствие них по всей A, вы можете использовать .ravel() -

A.ravel()[np.in1d(A,B)] = 0 

Я знаю .ravel() вид и из документации, кажется .flat не создает копию либо, поэтому они должны быть дешевой.

+0

Это здорово, не понимал, что я могу сделать это с индексированием. Смогу ли я использовать один и тот же подход, если бы я не питался нарезанным массивом, а вместо этого был полный массив 'A'? – user3357979

+0

@ пользователь3357979 Yup! Такой же подход должен работать и там. Итак, что-то вроде 'A [np.in1d ​​(A, B) .reshape (A.shape [0], - 1)] = 0'. – Divakar

+0

Просто предупреждение, это изменит 'A' на месте, не даст вам массив' result': вы потеряете оригинал 'A', в случае, если это имеет значение. – askewchan

-2

Вот как это сделать, не используя in1d(). Вы можете использовать обычный оператор Python in с ravel -ED версии вашего массива:

listed = [aa in B for aa in A[:, 3:].ravel()] 

# mask for unaffected left columns of A 
mask1 = np.array([False]*A.shape[0]*3) 
mask1.shape = (A.shape[0], 3) 

# mask for affected right columns of A 
mask2 = np.array(listed) 
mask2.shape = (A.shape[0], A.shape[1]-3) 

# join masks together so you have a mask with same dimensions as A 
mask = np.hstack((mask1, mask2)) 

result = A.copy() 
result[mask] = 0 

Или более кратко:

listed = [aa in B for aa in A[:, 3:].ravel()] 
listed_array = np.array(listed) 
listed.shape = (A.shape[0], A.shape[1]-3) 
A[:, 3:][listed_array] = 0 

Вы, вероятно, лучше с in1d() но приятно знать, что есть другие варианты.

Смежные вопросы