Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

with:

import numpy as np
array = get_array()

I need to do the following thing:

for i in range(len(array)):
    if random.uniform(0, 1) < prob:
        array[i] = not array[i]

with array being a numpy.array.

I wish I could do something similar to:

array = np.where(np.random.rand(len(array)) < prob, not array, array)

but I obtain the following result (referring to 'not array'):

The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Why can I take the value of array but not its negation?

Currently I solved with:

array = np.where(np.random.rand(len(array)) < prob, - array + 1, array)

but it looks really clumsy to me.

Thank you for your help

p.s.: I don't care if the statement modifies array or not. I just need the result of the operation.

just another question: I want to do this change for 2 reasons: readability and efficiency. Is there a real performance improvement with it? Thank you again

share|improve this question

3 Answers

up vote 15 down vote accepted

I suggest using

array ^= numpy.random.rand(len(array)) < prob

This is probably the most efficient way of getting the desired result. It will modify the array in place, using "xor" to invert the entries which the random condition evaluates to True for.

Why can I take the value of array but not its negation?

You can't take the truth value of the array either:

>>> bool(array)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

The not operator implicitly tries to convert its operand to bool, and then returns the opposite truth value. It is not possible to overload not to perform any other behaviour. To negate a NumPy array of bools, you can use

~array

or

numpy.logical_not(array)

or

numpy.invert(array)

though.

share|improve this answer

Perhaps this will help you to move on.

share|improve this answer
logical_not did the trick. I can't fully grasp the difference with the "simple" not though. – heapOverflow Feb 14 '11 at 12:25
1  
The point is that not array is ambiguous: in Python you can evaluate almost anything sensibly as a bool, so it is unclear to the interpreter whether you want the a elementwise negation or the negation of the array object, considered as a Boolean. – katrielalex Feb 14 '11 at 12:42
@heapOverflow: This might be relevant for you mail-archive.com/[email protected]/msg10700.html. Thanks – eat Feb 14 '11 at 12:42

putmask is very efficient if you want to replace selected elements:

import numpy as np

np.putmask(array, numpy.random.rand(array.shape) < prob, np.logical_not(array))
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.