Numpy subrange assignment with extended mixed indexing
Original question
I am getting a very strange error message when I try to assign some elements to an array. I am using a combination of slice and index set. See the next simple example.
import scipy as sp
a = sp.zeros((3, 4, 5))
b = sp.ones((4, 5))
I = sp.array([0, 1, 3])
b[:, I] = a[0, :, I]
This code calls the following ValueError
:
ValueError: Shape Mismatch: An array of shape values (3,4) could not be passed to index the result of shape (3,4)
-
Following actions
Use caution when using a combination of slice and seq. whole numbers. As stated on github:
x = rand(3, 5, 7)
print(x[0, :, [0,1]].shape)
# (2, 5)
print(x[0][:, [0,1]].shape)
# (5, 2)
This is how numpy works, but it's still a little confusing that x [0] [:, I] is not the same as x [0,:, I]. Since this is the behavior I want, I want to use x [0] [:, I] in my code.
source to share
It looks like there are some mistakes when copying your code to the question.
But I suspect there is a known indexing issue:
In [73]: a=np.zeros((2,3,4)); b=np.ones((3,4)); I=np.array([0,1])
Make I
2 elements. Indexing b
gives the expected (3,2) shape. 3 rows from slice, 2 columns from I
indexing
In [74]: b[:,I].shape
Out[74]: (3, 2)
But with 3d a
we get a transposition.
In [75]: a[0,:,I].shape
Out[75]: (2, 3)
and the assignment will result in an error
In [76]: b[:,I]=a[0,:,I]
...
ValueError: array is not broadcastable to correct shape
First it puts the element size 2 being specified I
and 3 elements from the :
second. This is the case of the mixed forward indexing discussed earlier - and there is the bug issue. (I'll have to watch them).
You are probably using new numpy
(or scipy
) and getting a different error message.
He documented that indexing with two arrays or lists and a slice in the middle puts a slice at the end, for example.
In [86]: a[[[0],[0],[1],[1]],:,[0,1]].shape
Out[86]: (4, 2, 3)
The same thing happens with a[0,:,[0,1]]
. But there is a good argument that this should not be the case.
As for the fix, you can move the value or change the indexing
In [88]: b[:,I]=a[0:1,:,I]
In [90]: b[:,I]=a[0,:,I].T
In [91]: b
Out[91]:
array([[ 0., 0., 1., 1.],
[ 0., 0., 1., 1.],
[ 0., 0., 1., 1.]])
In [92]: b[:,I]=a[0][:,I]
source to share
Here's how I get this error with indices [0,1,4]
:
IndexError: index 4 is out of bounds for axis 2 with size 4
Assumes the value is 4
used as an index, while SIZE 4 implies that the maximum index will be 3.
EDIT: now that you've changed it to [0, 1, 3]
, it works fine.
EDIT: With your current code, I get the same error, but when I print the arrays themselves, they are transverse:
print b[:, I]
print a[0, :, I]
[[ 1. 1. 1.]
[ 1. 1. 1.]
[ 1. 1. 1.]
[ 1. 1. 1.]]
[[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]]
source to share
First of all, it looks like line 6 is missing a comma:
I = sp.array([0,1,4])
Second, I would expect a value of 4 in the array I would raise an IndexError, since both a and b have a maximum size of 4. I suspect you can:
I = sp.array([0,1,3])
Making these changes runs the program for me and I got b as:
[[ 0. 0. 1. 0.]
[ 0. 0. 1. 0.]
[ 0. 0. 1. 0.]]
I suspect what you want.
source to share