Как сопоставить пары значений, содержащихся в двух числовых массивах - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть два набора координат, и я хочу узнать, какие координаты набора coo идентичны любым координатам в наборе targets.Я хочу знать индексы в наборе coo, что означает, что я хотел бы получить список индексов или bools.

import numpy as np

coo = np.array([[1,2],[1,6],[5,3],[3,6]]) # coordinates
targets = np.array([[5,3],[1,6]]) # coordinates of targets

print(np.isin(coo,targets))

[[ True False]
 [ True  True]
 [ True  True]
 [ True  True]]

Желаемый результат будет одним из следующих двух:

[False True True False] # bool list
[1,2] # list of concerning indices

Моя проблема в том, что ...

  • np.isin не имеет атрибута axis, чтобы я мог использовать axis=1.
  • дажеприменение логического и к каждой строке вывода вернет True для последнего элемента, что неверно.

Я знаю о циклах и условиях, но я уверен, что Pythonоснащен способами для более элегантного решения.

Ответы [ 4 ]

0 голосов
/ 24 февраля 2019

Пакет numpy_indexed реализует функциональность этого типа в векторизованном виде (отказ от ответственности: я являюсь его автором).К сожалению, NumPy не хватает этой функциональности из коробки;Я начал numpy_indexed с намерением объединить его в numpy, но есть некоторые проблемы с обратной совместимостью, и такие большие пакеты имеют тенденцию двигаться медленно.Так что этого не произошло за последние 3 года;но экосистема пакетов Python работает так хорошо, что просто добавить еще один пакет в вашу среду на самом деле так же просто.

import numpy_indexed as npi
bools = npi.in_(targets, coo)

Это будет иметь временную сложность, аналогичную сложности решения, опубликованного @Источник (логарифмический, а не линейный, согласно принятому в настоящее время ответу), а также библиотека npi обеспечат вам безопасность автоматических тестов и множество других удобных опций, если вы решите подойти к проблеме с несколько иной точки зрения.

0 голосов
/ 22 февраля 2019

Используя методы all и any из ответа @ yatu, я попытался понять некоторые вложенные списки.Хотя вещание значительно чище.

np.array([[x==y for x in coo] for y in targets]).all(2).any(axis=0)

возвращает:

array([False, True, True, False])
0 голосов
/ 24 февраля 2019

Вот простое и интуитивно понятное решение, которое на самом деле использует numpy.isin(), чтобы сопоставлять кортежи , а не отдельные цифры:

# View as a 1d array of tuples
coo_view     = coo.view(dtype='i,i').reshape((-1,))
targets_view = targets.view(dtype='i,i').reshape((-1,))

result = np.isin(coo_view, targets_view)
print (result)
print(result.nonzero()[0])

Вывод:

[False  True  True False]
[1 2]

Примечания:

  1. Создание этих представлений не требует копирования данных.
  2. dtype='i,i' указывает, что мы хотим, чтобы каждый элемент представления был кортежем из двух целых чисел
0 голосов
/ 22 февраля 2019

Вот один из способов использования broadcasting:

(coo[:,None] == targets).all(2).any(1)
# array([False,  True,  True, False])

Подробности

Проверка для каждой строки в coo совпадает ли он с другим в target путем прямого сравнения, добавив первую ось к coo, чтобы она стала транслируемой против targets:

(coo[:,None] == targets)

array([[[False, False],
        [ True, False]],

       [[False, False],
        [ True,  True]],

       [[ True,  True],
        [False, False]],

       [[False, False],
        [False,  True]]])

Затем проверьте, какие ndarrays вдольвторая ось имеет значения all до True:

(coo[:,None] == targets).all(2)

array([[False, False],
       [False,  True],
       [ True, False],
       [False, False]])

И, наконец, используйте any, чтобы проверить, какие строки имеют хотя бы одну True.

...