Подтвердить что ты не робот

Python: число индексов пересечения

Как я могу получить индексы точек пересечения между двумя массивами numpy? Я могу получить пересекающиеся значения с помощью intersect1d:

import numpy as np

a = np.array(xrange(11))
b = np.array([2, 7, 10])
inter = np.intersect1d(a, b)
# inter == array([ 2,  7, 10])

Но как я могу получить индексы в a значений в inter?

4b9b3361

Ответ 1

Вы можете использовать булевский массив, созданный in1d, для индексации arange. Реверсирование a так, чтобы индексы отличались от значений:

>>> a[::-1]
array([10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0])
>>> a = a[::-1]

intersect1d по-прежнему возвращает те же значения...

>>> numpy.intersect1d(a, b)
array([ 2,  7, 10])

Но in1d возвращает логический массив:

>>> numpy.in1d(a, b)
array([ True, False, False,  True, False, False, False, False,  True,
       False, False], dtype=bool)

Что можно использовать для индексации диапазона:

>>> numpy.arange(a.shape[0])[numpy.in1d(a, b)]
array([0, 3, 8])
>>> indices = numpy.arange(a.shape[0])[numpy.in1d(a, b)]
>>> a[indices]
array([10,  7,  2])

Чтобы упростить вышеизложенное, вы можете использовать nonzero - это, вероятно, самый правильный подход, потому что он возвращает кортеж равномерных списков X, Y... координат:

>>> numpy.nonzero(numpy.in1d(a, b))
(array([0, 3, 8]),)

Или, что эквивалентно:

>>> numpy.in1d(a, b).nonzero()
(array([0, 3, 8]),)

Результат может быть использован как индекс для массивов той же формы, что и a без проблем.

>>> a[numpy.nonzero(numpy.in1d(a, b))]
array([10,  7,  2])

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

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

>>> numpy.argwhere(numpy.in1d(a, b))
array([[0],
       [3],
       [8]])

Ответ 2

Если вам нужно получить уникальные значения, заданные intersect1d:

import numpy as np

a = np.array([range(11,21), range(11,21)]).reshape(20)
b = np.array([12, 17, 20])
print(np.intersect1d(a,b))
#unique values

inter = np.in1d(a, b)
print(a[inter])
#you can see these values are not unique

indices=np.array(range(len(a)))[inter]
#These are the non-unique indices

_,unique=np.unique(a[inter], return_index=True)

uniqueIndices=indices[unique]
#this grabs the unique indices

print(uniqueIndices)
print(a[uniqueIndices])
#now they are unique as you would get from np.intersect1d()

Вывод:

[12 17 20]
[12 17 20 12 17 20]
[1 6 9]
[12 17 20]

Ответ 3

Перейдем к этому шаг за шагом.

Другое решение

Сначала мы создаем массив numpy с нулями

c = np.zeros(len(a))
print c
>>> [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]

Во-вторых, измените значение массива c с использованием индекса пересечения

c[inter] = 1
print c
>>>[ 0.  0.  1.  0.  0.  0.  0.  1.  0.  0.  1.]

Последний шаг, используйте характеристику np.nonzero(), он вернет index ненулевого термина

inter_with_idx = np.nonzero(c)
print inter_with_idx
>>>array([ 2, 7, 10])

Ссылка

[1] numpy.nonzero