1

I want to do array indexing. I would have expected the result to be [0,1,1,0], however I just get an error. How can I do this type of indexing?

a_np_array=np.array(['a','b','c','d'])
print a_np_array in ['b', 'c']

Traceback (most recent call last):
File "dfutmgmt_alpha_osis.py", line 130, in <module>
print a_np_array in ['b', 'c']
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Up top, i actually meant to say [False,True,True,False] not [0,1,1,0] as I want the bools so i can do indexing

2
  • OK. I checked the documentation and this seems to be what I am looking for. Can you explain why my method does not work? I am surprised that there is no kind of array index like method to do this. Commented Mar 2, 2015 at 16:27
  • I have moved my comment to answer with some more explanation. Commented Mar 2, 2015 at 17:32

2 Answers 2

2

Try this list comprehension:

>>> print [int(x in ['b', 'c']) for x in a_np_array]
[0, 1, 1, 0]

Utilizing the fact that int(True) == 1 and int(False) == 0

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

Comments

1

First of all you cannot use [0,1,1,0] for indexing here, so you're using the wrong term.

>>> a_np_array[[0,1,1,0]]  # Not useful at all
array(['a', 'b', 'b', 'a'], 
      dtype='|S1')

If I understood this correctly you're simply trying to check whether items of a_np_array exist in ['b', 'c'], for that use numpy.in1d, but as it returns boolean array we just need to convert it integer array.

>>> np.in1d(a_np_array, ['b','c'])
array([False,  True,  True, False], dtype=bool)
>>> np.in1d(a_np_array, ['b','c']).astype(int)
array([0, 1, 1, 0])

Coming to why a_np_array in ['b', 'c'] didn't work?

Here the in operator will call the __contains__ method of the list object(['b', 'c']) and then for each object in list Python will use the method PyObject_RichCompareBool to compare each item to a_np_array. PyObject_RichCompareBool first of all simply checks if the items to be compared are the same object, i.e same id(), if yes return 1 right away otherwise call PyObject_RichCompare on them. Hence this will work:

>>> a_np_array in [a_np_array, 'c', 'a']
True

But this won't:

>>> a_np_array in [a_np_array.copy(), 'c', 'a']
Traceback (most recent call last):
  File "<ipython-input-405-dfe2729bd10b>", line 1, in <module>
    a_np_array in [a_np_array.copy(), 'c', 'a']
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Now Python will check whether the object returned by PyObject_RichCompare is already a boolean type, i.e True or False(This is done using PyBool_Check and Py_True), if it is then return the result immediately otherwise call PyObject_IsTrue to check whether the object can be considered a truthy object, this is done by calling __nonzero__ method of the object. For a NumPy array this will end up calling bool() on the returned object which is going to raise an error you're getting. Here NumPy expects you to call either all() or any() to check whether all items are True or at least one.

>>> bool(a_np_array == 'a')
Traceback (most recent call last):
  File "<ipython-input-403-b7ced85c4f02>", line 1, in <module>
    bool(a_np_array == 'a')
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Links to source code:

Comments

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.