invis - 8 months ago 172

Python Question

How can I get the indices of intersection points between two numpy arrays? I can get intersecting values with

`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])

But how can I get the indices into

`a`

`inter`

Answer

You could use the boolean array produced by `in1d`

to index an `arange`

. Reversing `a`

so that the indices are different from the values:

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

`intersect1d`

still returns the same values...

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

But `in1d`

returns a boolean array:

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

Which can be used to index a range:

```
>>> 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])
```

To simplify the above, though, you could use `nonzero`

-- this is probably the most correct approach, because it returns a tuple of uniform lists of `X`

, `Y`

... coordinates:

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

Or, equivalently:

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

The result can be used as an index to arrays of the same shape as `a`

with no problems.

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

But note that under many circumstances, it makes sense just to use the boolean array itself, rather than converting it into a set of non-boolean indices.

Finally, you can also pass the boolean array to `argwhere`

, which produces a slightly differently-shaped result that's not as suitable for indexing, but might be useful for other purposes.

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