Reputation: 1890
I got a basic error with strange output that I do not understand verywell:
step to reproduce
arr1 = np.zeros([6,10,50])
arr2 = np.zeros([6,10])
arr1[:, :, range(25,26,1)] = [arr2]
That generate this error:
ValueError: shape mismatch: value array of shape (1,6,10) could not be broadcast to indexing result of shape (1,6,10)
Could anyone explain what I'm doing wrong ?
Upvotes: 0
Views: 1522
Reputation: 26906
Since range(25, 26, 1)
is actually a single number, you could use either:
arr1[:, :, 25:26] = arr2[..., None]
or:
arr1[:, :, 25] = arr2
in place of arr1[:, :, range(25,26,1)] = [arr2]
.
Note that for ranges/slices that do not reduce to a single number the first line would use broadcasting.
The reason why your original code does not work is that you are mixing NumPy arrays and Python list
s in a non-compatible way because NumPy interprets [arr2]
as having shape (1, 6, 10)
while the result expects a shape (6, 10, 1)
(the error you are getting is substantially about that.)
The above solution targets at making sure that arr2
is in a compatible shape.
Another possibility would have been to change the shape of the recipient, which would allow you to assign [arr2]
, e.g.:
arr1 = np.zeros([50,6,10])
arr2 = np.zeros([6,10])
arr1[25:26, :, :] = [arr2]
This method may be less efficient though, since arr2[..., None]
is just a memory view of the same data in arr2
, while [arr2]
is creating (read: allocating new memory for) a new list
object, which would require some casting (happening under the hood) to be assigned to a NumPy array.
Upvotes: 1
Reputation: 12221
Add an extra dimension to arr2
:
arr1[:, :, range(25,26,1)] = arr2.reshape(arr2.shape + (1,))
Easier notation for range
as used here:
arr1[:, :, 25:26)] = arr2.reshape(arr2.shape + (1,))
(and slice(25,26,1)
, or slice(25,26)
, could also work; just to add to the options and possible confusion.)
Or insert an extra axis at the end of arr2
:
arr1[..., 25:26] = arr2[..., np.newaxis]
(where ...
means "as many dimensions as possible"). You can also use None
instead of np.newaxis
; the latter is probably more explicit, but anyone knowing NumPy will recognise None
as inserting an extra dimension (axis).
Of course, you could also set arr2
to be 3-dimensional from the start:
arr2 = np.zeros([6,10,1])
Note that broadcasting does work when used from the left:
>>> arr1 = np.zeros([50,6,10]) # Swapped ("rolled") dimensions
>>> arr2 = np.zeros([6,10])
>>> arr1[25:26, :, :] = arr2 # No need to add an extra axis
It's just that it doesn't work when used from the right, as in your code.
Upvotes: 1