Numpy unexpected (for me) behaviour
Hello, In an effort to suppress for loops, I have arrived to the following situation. Through vectorial logical operations I generate a set of indices for which the contents of an array have to be incremented. My problem can be reduced to the following: #This works import numpy a=numpy.zeros(10) b=numpy.ones(4, numpy.int) for i in b: a[i] += 1 #a[1] contains 4 at the end #This does not work import numpy a=numpy.zeros(10) b=numpy.ones(4, numpy.int) a[b] += 1 #a[1] contains 1 at the end Is that a bug or a feature? Is there a way I can achieve the first result without a for loop? In my application the difference is a factor 10 in execution time (1000 secons instead of 100 ...) Thanks, Armando
On Fri, Jan 23, 2009 at 01:39, Matthew Brett <matthew.brett@gmail.com> wrote:
Hi,
#This does not work import numpy a=numpy.zeros(10) b=numpy.ones(4, numpy.int) a[b] += 1
The problem here is that you are setting a[1] to a[1]+1.
I think you want:
import numpy a=numpy.zeros(10) b=numpy.ones(4, numpy.bool) a[b] += 1
Judging from his for loop, he does want the integer array. He's doing something like histogramming.  Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth."  Umberto Eco
On Fri, Jan 23, 2009 at 01:11, V. Armando Sole <sole@esrf.fr> wrote:
Hello,
In an effort to suppress for loops, I have arrived to the following situation.
Through vectorial logical operations I generate a set of indices for which the contents of an array have to be incremented. My problem can be reduced to the following:
#This works import numpy a=numpy.zeros(10) b=numpy.ones(4, numpy.int)
for i in b: a[i] += 1 #a[1] contains 4 at the end
#This does not work import numpy a=numpy.zeros(10) b=numpy.ones(4, numpy.int) a[b] += 1
#a[1] contains 1 at the end
Is that a bug or a feature?
It is an inevitable consequence of several features interacting together. Basically, Python expands "a[b] += 1" into this: c = a[b] d = c.__iadd__(1) a[b] = d Basically, the array c doesn't know that it was created by indexing a, so it can't do the accumulation you want.
Is there a way I can achieve the first result without a for loop? In my application the difference is a factor 10 in execution time (1000 secons instead of 100 ...)
In [6]: bincount? Type: builtin_function_or_method Base Class: <type 'builtin_function_or_method'> String Form: <builtin function bincount> Namespace: Interactive Docstring: bincount(x,weights=None) Return the number of occurrences of each value in x. x must be a list of nonnegative integers. The output, b[i], represents the number of times that i is found in x. If weights is specified, every occurrence of i at a position p contributes weights[p] instead of 1. See also: histogram, digitize, unique.  Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth."  Umberto Eco
participants (3)

Matthew Brett

Robert Kern

V. Armando Sole