Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Numpy fancy indexing and assignment

Normally numpy forces the left and right side of an assignment to match, so for example if I do a[:] = b, b must be the same shape or broadcast to the same shape as a. But there seems to be an exception to that rule:

>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b = a.copy()
>>> a[[0,1,2]] = b[::2]
>>> a
array([0, 2, 4, 3, 4, 5, 6, 7, 8, 9])
>>> a[np.arange(10)] = b[:2]
>>> a
array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1])

It seems to only work with 1d arrays and only if there is fancy indexing on the left side of the assignment, but I haven't been able to find documentation for this behavior anywhere. Is this behavior documented, if so where, and also can someone give an example of when it might be useful?

Update:

It seems that the numpy flatiter type behaves this way too, is there some connection between flatiter and fancy indexing that I don't know about?

>>> a.flat = [10,11]
>>> a
array([10, 11, 10, 11, 10, 11, 10, 11, 10, 11])
>>> a.flat[:] = [2,3,4]
>>> a
array([2, 3, 4, 2, 3, 4, 2, 3, 4, 2])
>>> a.flat = range(100)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
like image 250
Bi Rico Avatar asked Feb 24 '12 01:02

Bi Rico


1 Answers

I think this behavior is modeled on R and its ancestor S/S-plus. That's how list assignment ("vector" assignment) works there, and it's called "recycling". The R project website talks about it, but I found a more illuminating explanation at this link. In R, a vector is a collection of measurements, so it makes sense to pad or trim it the way it does. How much of this logic has made it to numpy, and why, is still a good question.

like image 193
alexis Avatar answered Sep 19 '22 01:09

alexis