Нахождение индекса элемента в массиве NumPy без использования цикла for - PullRequest
1 голос
/ 24 марта 2019

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

my_array = np.matrix([[3, 7, 0, 0],
                      [0, 2, 0, 0],
                      [0, 0, 0, 0],
                      [0, 0, 1, 0]])

Мне нужно найти индекс каждого элемента в этом массиве, в котором сумма элементов в этой строке и столбце == 0. В этом случае ответом будет (2, 3), поскольку сумма элементов в вторая строка = 0 и сумма элементов в 3-м столбце = 0. Пока что я придумал это:

solution = [(i, j) for i in range(my_array.shape[0]) for j in range(my_array.shape[1]) if 1 not in my_array[i] and 1 not in my_array[:, j]]

Проблема в том, что я хочу сделать это без использования цикла for.

Я пытался использовать np.where и np.sum, в конечном итоге это:

np.where(np.sum(my_array, axis=1) == 0 and np.sum(my_array, axis=0) == 0)

но я получаю эту ошибку:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Любое предложение о том, как я могу исправить эту ошибку или просто использовать другой метод для поиска индексов?

Ответы [ 2 ]

2 голосов
/ 24 марта 2019

Проблема с вашим выражением where возникает внутри него, когда вы пытаетесь объединить два условия:

In [210]: np.sum(arr, axis=1) == 0 and np.sum(arr, axis=0) == 0                 
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-210-46c837435a31> in <module>
----> 1 np.sum(arr, axis=1) == 0 and np.sum(arr, axis=0) == 0

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
In [211]: (np.sum(arr, axis=1) == 0) & (np.sum(arr, axis=0) == 0)               
Out[211]: array([False, False, False, False])

Вы должны обернуть тест == внутри (), чтобы он появился первым, иВы должны использовать & для поэтапного выполнения and.and - это скалярная операция, которая плохо работает с логическими массивами.

Тесты строк и столбцов:

In [212]: arr.sum(0)==0                                                         
Out[212]: array([False, False, False,  True])
In [213]: arr.sum(1)==0                                                         
Out[213]: array([False, False,  True, False])

, но вам нужна какая-то внешняя или декартова комбинация,не простая поэлементная комбинация (это было бы более очевидно, если бы было различное количество строк и столбцов).

In [218]: (arr.sum(1)==0)[:,None] & (arr.sum(0)==0)                             
Out[218]: 
array([[False, False, False, False],
       [False, False, False, False],
       [False, False, False,  True],
       [False, False, False, False]])
In [219]: np.where(_)                                                           
Out[219]: (array([2]), array([3]))

Или с параметром keepdims sum:

In [220]: arr.sum(0, keepdims=True)==0                                          
Out[220]: array([[False, False, False,  True]])
In [221]: arr.sum(1, keepdims=True)==0                                          
Out[221]: 
array([[False],
       [False],
       [ True],
       [False]])
In [222]: np.where(_220 & _221)             # Out[220] etc                                    
Out[222]: (array([2]), array([3]))
0 голосов
/ 24 марта 2019

Вот решение с использованием продукта от itertools. Создание списка строк и столбцов с суммами == 0 и поиск комбинаций между ними.

from itertools import product

my_array = np.matrix([[3, 7, 0, 0],
                      [0, 2, 0, 0],
                      [0, 0, 0, 0],
                      [0, 0, 1, 0]])


a = np.argwhere(my_array.sum(axis = 1) == 0)[:,0]
b = np.argwhere(my_array.sum(axis = 0) == 0)[:,1]

np.array(list(product(a,b)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...