Jérémy
Jérémy

Reputation: 1890

ValueError: shape mismatch: with same shape

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

Answers (2)

norok2
norok2

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 lists 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

9769953
9769953

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

Related Questions