Python найти координаты в трехмерном массиве значения - PullRequest
0 голосов
/ 14 июля 2020

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

table = np.array([
    [
        [1,4,8,6],
        [8]],
    [
        [4],
        [9],
        [5]],
    [
        [6],
        [4]],
    [
        [2],
        [1]]])

На основе this связанный вопрос. У меня есть следующий код:

print(np.argwhere(table == 1))

Этот код делает именно то, что я хочу (выводит на печать трехмерные координаты вхождений значений) для «более простого» трехмерного массива. Но не работает для моего массива.

Почему мой текущий код не работает с моим массивом? Как получить тот же результат на моем массиве?

Массив, на котором он работает:

table = np.array([
    [
        [ 1, 2, 3],
        [ 8, 4, 11]],
    [   
        [ 1, 4, 4],
        [ 8, 5, 9]],
    [
        [ 3, 8, 6],
        [ 11, 9, 8]],
    [   
        [ 3, 7, 6],
        [ 9, 3, 7]]])

1 Ответ

1 голос
/ 14 июля 2020

Когда вы печатаете свою (первую) таблицу , результат будет:

array([list([[1, 4, 8, 6], [8]]), list([[4], [9], [5]]), list([[6], [4]]),
       list([[2], [1]])], dtype=object)

т.е. это массив 1-D , содержащий 4 элемента список тип.

Причина, по которой np.where не может найти экземпляры 1 , заключается в том, что он просматривает каждый элемент и сравнивает его с заданным значением. Эта функция при проверке конкретного элемента массива не «ныряет» в этот объект (не проверяет отдельные подэлементы элемента (если это список)).

Все, что np. где делает при проверке элемента (типа список ), он проверяет: является ли этот элемент == 1. Поскольку это не так, то он рассматривается как не- соответствие. Другие элементы тоже.

Отредактируйте после комментария от 15.07

Если вы определите свою таблицу как:

table2 = np.array(list([
    list([[1,4,8,6], [8,0,0,0], [0,0,0,0]]),
    list([[4,0,0,0], [9,0,0,0], [5,0,0,0]]),
    list([[6,0,0,0], [4,0,0,0], [0,0,0,0]]),
    list([[2,0,0,0], [1,0,0,0], [0,0,0,0]])]))

(со всеми списками то же size), Pandas достаточно умен, чтобы преобразовать его в:

array([[[1, 4, 8, 6],
        [8, 0, 0, 0],
        [0, 0, 0, 0]],

       [[4, 0, 0, 0],
        [9, 0, 0, 0],
        [5, 0, 0, 0]],

       [[6, 0, 0, 0],
        [4, 0, 0, 0],
        [0, 0, 0, 0]],

       [[2, 0, 0, 0],
        [1, 0, 0, 0],
        [0, 0, 0, 0]]])

Run table.shape, и вы увидите (4, 3, 4).

Затем запустите table.dtype, и вы увидите dtype('int32'), так что теперь это «обычный» Numpy массив из int s.

В таком случае np.argwhere(table == 1) находит индексы ячеек, содержащих только 1 .

Но ваша таблица настолько "странная", что Pandas не предназначена для.

Чтобы найти индексы каждого 1 в этих (вложенных) списках, вы можете перебирать свой массив (используя nd.iter ) и искать внутри каждого элемента индексы 1 если есть. Что-то вроде:

it = np.nditer(table, flags=['f_index', 'refs_ok'])
for x in it:
    print(f'Index {it.index}: {x}')
    res = [(i, el.index(1)) for i, el in enumerate(x[()]) if 1 in el]
    if len(res) == 0:
        print('    Nothing found')
    else:
        print(f'    Found at: {res}')

Обратите внимание, что после x есть несколько странная конструкция, а именно [()] . Причина в том, что:

  • Ваша таблица представляет собой массив объектов 1-D .
  • Каждый элемент на самом деле 0-D массив, содержащий одиночный объект (вложенный список).
  • [()] - это способ получить единственный содержащийся объект. Вы получаете доступ к элементу по индексу , но значением индекса является пустой кортеж (без фактического значения индекса).

Для вашей таблицы напечатан приведенный выше код :

Index 0: [[1, 4, 8, 6], [8]]
    Found at: [(0, 0)]
Index 1: [[4], [9], [5]]
    Nothing found
Index 2: [[6], [4]]
    Nothing found
Index 3: [[2], [1]]
    Found at: [(1, 0)]

При необходимости переделайте его под свои нужды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...