Reputation: 43
While using the example from NumPy Book while starting out with NumPy I noted an example:
a = zeros((4, 5))
b = ones(6)
add(b, b, a[1:3, 0:3].flat)
print(a)
returns
array([[0, 0, 0, 0, 0]
[2, 2, 2, 0, 0]
[2, 2, 2, 0, 0]
[0, 0, 0, 0, 0]])
However, when I try this code, it results in the following error:
add(b, b, a[1:3, 0:3].flat)
TypeError: return arrays must be of ArrayType"
Could anyone please shed some light on this problem?
Upvotes: 4
Views: 152
Reputation: 152587
If you have 2 arguments for numpy.add
they are taken as the two operands that are added
. If you give 3 arguments the first two are the ones that are added and the third one is the result
. Well actually not the result but the array where the result should be saved in.
So you added b
with b
and wanted to store it in a[1:3, 0:3].flat
.
Let's just try to np.add(b, b)
which gives
import numpy as np
a = np.zeros((4, 5))
b = np.ones(6)
np.add(b, b)
# returns array([ 2., 2., 2., 2., 2., 2.])
So now I tried a[1:3, 0:3].flat
which returns <numpy.flatiter at 0x22204e80c10>
. This means that it returns an iterator
so it's no array. But we don't need an iterator we want an array. There is a method called ravel()
. So trying a[1:3, 0:3].ravel()
returns:
array([ 0., 0., 0., 0., 0., 0.])
so we have an array. Especially the array is also usable for storing the result (same shape!). So I tried:
np.add(b, b, a[1:3, 0:3].ravel())
# array([ 2., 2., 2., 2., 2., 2.])
But let's see if a
has changed:
a
#array([[ 0., 0., 0., 0., 0.],
# [ 0., 0., 0., 0., 0.],
# [ 0., 0., 0., 0., 0.],
# [ 0., 0., 0., 0., 0.]])
So a
hasn't changed. That's because ravel()
only returns a view (assignment would propagate to the unravelled array) if possible otherwise it returns a copy. And saving the result in a copy is rather pointless because the whole point of the out
parameter is that the operation is done in-place. I'm only guessing why a copy is made but I think it's because we take a portion out of a bigger array where the portion is not contiguous in the memory.
So I would propose that you don't use the out
parameter in this case but use the return of the np.add
and store it inside the specified region in a
:
a[1:3, 0:3] = np.add(b, b).reshape(2,3) # You need to reshape here!
a
#array([[ 0., 0., 0., 0., 0.],
# [ 2., 2., 2., 0., 0.],
# [ 2., 2., 2., 0., 0.],
# [ 0., 0., 0., 0., 0.]])
Also a[1:3, 0:3].flat = np.add(b, b)
works.
I think the book is either outdated and it worked with an older numpy
version or it never worked at all and it was a mistake in the book.
Upvotes: 3