Hi, I'm trying to figure out how to use fancy indexing for ordinary (non-sparse) arrays. On reading, it's clear enough what is meant: a = arange(3) a[[1,1,2]] -> array([1,1,2]) But when writing it's not so clear what should happen: a[[1,1,2]] = array([1,2,3]) a -> array([0,2,3]) All right, the assignment a[1]=... has been done twice, so I only see the effects of the second. Fair enough. But: a[[1,1,2]] += 1 a -> array([0,3,4]) That is, a[[1,1,2]] += 1 is equivalent to a[[1,1,2]] = a[[1,1,2]] + 1 and not for i in [1,1,2]: a[i]+=1 Is this really intended? It's surprising, it seems like that forces numpy to make a copy, and it leaves me with the question of how to implement the second without a loop... Well, for a better example: x = array([...]) i1 = ravel(ix_(arange(len(x)),arange(len(x)))[...,0]) i2 = ravel(ix_(arange(len(x)),arange(len(x)))[...,1]) dx = f(x[i1],x[i2]) # compute all the pairwise interactions # x[i1] += dx for (i,a) in enumerate(i1): x[a]+=dx[i] How do I write something like this without a loop? Sort i1 and concoct something that adds all the values with the same index before adding it to x? Thanks, A. M. Archibald
A. M. Archibald wrote:
Hi,
I'm trying to figure out how to use fancy indexing for ordinary (non-sparse) arrays. On reading, it's clear enough what is meant:
a = arange(3) a[[1,1,2]] -> array([1,1,2])
But when writing it's not so clear what should happen:
a[[1,1,2]] = array([1,2,3]) a -> array([0,2,3])
All right, the assignment a[1]=... has been done twice, so I only see the effects of the second. Fair enough. But:
a[[1,1,2]] += 1 a -> array([0,3,4])
That is, a[[1,1,2]] += 1 is equivalent to
a[[1,1,2]] = a[[1,1,2]] + 1
and not
for i in [1,1,2]: a[i]+=1
Is this really intended? It's surprising, it seems like that forces numpy to make a copy, and it leaves me with the question of how to implement the second without a loop...
We've gone over this before on the numpy-discussion list. Given the way that Python implements augmented assignment, there is no way for the array object to know that you wanted to do some kind of loop. Python implements that statement as something equivalent to tmp = a.__getitem__([1,1,2]) tmp.__iadd__(1) a.__setitem__([1,1,2], tmp) There is no place to implement the kind of loop that you want to see. Nor should we. According to the reference manual, augmented assignment methods should be implemented such that x += y is nearly equivalent to x = x + y with the exception of possible in-place modification of x. http://docs.python.org/ref/augassign.html -- 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 01/09/06, Robert Kern <robert.kern@gmail.com> wrote:
Nor should we. According to the reference manual, augmented assignment methods should be implemented such that
x += y
is nearly equivalent to
x = x + y
with the exception of possible in-place modification of x.
One could argue that what I was asking for is the appropriate notion of "in-place modification" in this context, but that's a technicality. I suppose either version will be surprising to somebody. Thanks for your prompt reply. A.M. Archibald
A. M. Archibald wrote:
On 01/09/06, Robert Kern <robert.kern@gmail.com> wrote:
Nor should we. According to the reference manual, augmented assignment methods should be implemented such that
x += y
is nearly equivalent to
x = x + y
with the exception of possible in-place modification of x.
One could argue that what I was asking for is the appropriate notion of "in-place modification" in this context, but that's a technicality.
Well, not quite. The idea that the manual is trying to express is that both forms, "x += y" and "x = x + y" should result in final values of "x" that are the equal to each other. The only difference should be that the *identities* of the objects finally referenced by "x" might be different. -- 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 (2)
-
A. M. Archibald -
Robert Kern