5

I need to find a vector in a numpy.array. For example, I have a np.array named e and I want to find the vector [1, 2] in e (meaning that I would like to have the index of the vector inside the matrix) but apparently my programm see the vector even when is not present:

enter image description here

The code I use to built e in the following:

import numpy as np
faces = np.array([[1,2,3,4],[5,6,2,1],[6,7,3,2],[7,8,4,3],[8,5,1,4],[8,7,6,5]])
e = np.zeros([6,4,2])
for k in range(len(faces)):
    a = [faces[k][0], faces[k][1]]
    b = [faces[k][1], faces[k][2]] 
    c = [faces[k][2], faces[k][3]]
    d = [faces[k][3], faces[k][0]]
    e[k] = np.array([a,b,c,d])
 print('e: %s' %e)

any clue how to solve this?

1
  • 2
    Including code was helpful. The image is superfluous; just include the stuff you tried in text form. Commented Oct 7, 2013 at 15:34

4 Answers 4

6

Don't use Python in with numpy arrays.

There are 6 x 4 pairs in e.

In [32]: e.shape
Out[32]: (6, 4, 2)

You are looking an element that matches both (i.e., all()) entries in the pair [1, 2].

In [33]: (e == np.array([1, 2])).all(-1)
Out[33]: 
array([[ True, False, False, False],
       [False, False, False, False],
       [False, False, False, False],
       [False, False, False, False],
       [False, False, False, False],
       [False, False, False, False]], dtype=bool)

The -1 in all(-1) refers the last dimension in the array, the part of the shape that constitutes pairs. Using -1 is probably more general than using 2, which would also work in this case.

It found the right match -- the only True value. You can see the shape of this result makes sense.

In [34]: (e == np.array([1, 2])).all(-1).shape
Out[34]: (6, 4)

To get the index of the first match you could do

x, y = (e == np.array([1, 2])).all(-1).argmax(1).argmax(), (e == np.array([1, 2])).all(-1).argmax(0).argmax()

but using np.argwhere suggested in CT Zhu's answer is definitely better.

Sign up to request clarification or add additional context in comments.

6 Comments

but then how can I take-have-print the index of the True value? Sorry, I'm a beginner.
when I'm looking for a different vector [1,4] it don't give the correct result: x = (e == np.array([1, 4])).all(-1).argmin(1).argmax() y = (e == np.array([1, 4])).all(-1).argmin(0).argmax() return x=0, y=0..why??
My mistake. See edited answer. I should be argmax in every case (never argmin). On a boolean array, argmax means "index of the first True value." For example, (e == np.array([1, 4])).all(-1).argmax(0).argmax() gives 2, properly.
"Don't use Python in with numpy arrays". Why do you state this?
Because it does not take advantage of vectorization and is therefore slow.
|
4

Try:

e[np.all((e-np.array([1,2]))==0, axis=2)]

Brief explanation. e-np.array([1,2]) returns [0,0] where it is [1,2] in array e. np.all(..., axis=2 returns the Boolean array: True if [0,0] False otherwise (so things such as [1,1] will become False). Finally, just slice it from e.

To get the index of [1,2]'s (there may be multiple sub vector [1,2]):

np.argwhere(np.all((e-array([1,2]))==0, axis=2))

2 Comments

it works exactly as I needed! Just one note: I get the warning that argwhere is an undefined name (I'm using python 2.7.5) I may need to import some packet but that's of course not a problem, thanks!
Yes, you are right. If you didn't have from numpy import * it will need to be np.argwhere. Edited.
2

You can also use the following trick to view your vectors as single items of np.void dtype:

e = np.ascontiguousarray(e)
dt = np.dtype((np.void, e.dtype.itemsize * e.shape[-1]))
e_view = e.view(dt)
search = np.array([1, 2], dtype=e.dtype).view(dt)

You can now extract the positions with np.in1d:

mask = np.in1d(e_view, search)
indices = np.unravel_index(np.where(mask), e.shape[:-1])

>>> indices
(array([[0]], dtype=int64), array([[0]], dtype=int64))

The return arrays is a tuple with the rows and columns of the occurrences of search, in this case there is only one, at (0, 0).

Comments

0

This will print out all the indices of e and whether it is equal to [1,2]. If you wanted to return the indices, instead of printing them, you could add (num, num2) to another list, and that would give you all the locations of [1,2]. Would need to be extended to work with arrays of more levels.

for num, item in enumerate(e):
    for num2, item2 in enumerate(item):                                    
        print ('e[{i}][{j}]: {truth}'.format(i=num, 
                                             j=num2, 
                                             truth = (item2 == [1,2]).all()))

Output:

e[0][0]: True                                                                                                          
e[0][1]: False                                                                                                         
e[0][2]: False                                                                                                         
e[0][3]: False                                                                                                         
e[1][0]: False                                                                                                         
e[1][1]: False                                                                                                         
e[1][2]: False                                                                                                         
e[1][3]: False                                                                                                         
e[2][0]: False                                                                                                         
e[2][1]: False                                                                                                         
e[2][2]: False                                                                                                         
e[2][3]: False                                                                                                         
e[3][0]: False                                                                                                         
e[3][1]: False                                                                                                         
e[3][2]: False                                                                                                         
e[3][3]: False                                                                                                         
e[4][0]: False                                                                                                         
e[4][1]: False                                                                                                         
e[4][2]: False                                                                                                         
e[4][3]: False                                                                                                         
e[5][0]: False                                                                                                         
e[5][1]: False                                                                                                         
e[5][2]: False                                                                                                         
e[5][3]: False

3 Comments

and if I wanted to print the element after the one that match? (or to save it into a variable)
not sure I quite get the question, but you could use this: gist.github.com/garth5689/6870607 Basically, just add an item to try and find the next element, and add it to the print string. It will print None on IndexErrors.
The benefit of using numpy is the first place is to avoid slow Python loops.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.