Вопрос:

Пересечение 2d и 1d Numpy массива

python arrays numpy intersection

464 просмотра

2 ответа

219 Репутация автора

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

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как одномерный массив, но я понятия не имею, как это сделать.

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

Автор: user3357979 Источник Размещён: 09.09.2015 01:54

Ответы (2)


6 плюса

174519 Репутация автора

Решение

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

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тоже не создается копия, поэтому они должны быть дешевыми .

Автор: Divakar Размещён: 09.09.2015 01:59

-2 плюса

1772 Репутация автора

Вот способ сделать это без использования in1d(). Вы можете использовать обычный in оператор Python с 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()но приятно знать, что есть и другие варианты.

Автор: sunny Размещён: 09.09.2015 03:15
Вопросы из категории :
32x32