Search code examples
numpybroadcasting

Numpy array changes shape when accessing with indices


I have a small matrix A with dimensions MxNxO

I have a large matrix B with dimensions KxMxNxP, with P>O

I have a vector ind of indices of dimension Ox1

I want to do:

B[1,:,:,ind] = A

But, the lefthand of my equation

 B[1,:,:,ind].shape

is of dimension Ox1xMxN and therefore I can not broadcast A (MxNxO) into it.

Why does accessing B in this way change the dimensions of the left side? How can I easily achieve my goal? Thanks


Solution

  • There's a feature, if not a bug, that when slices are mixed in the middle of advanced indexing, the sliced dimensions are put at the end.

    Thus for example:

    In [204]: B = np.zeros((2,3,4,5),int)
    In [205]: ind=[0,1,2,3,4]
    In [206]: B[1,:,:,ind].shape
    Out[206]: (5, 3, 4)
    

    The 3,4 dimensions have been placed after the ind, 5.

    We can get around that by indexing first with 1, and then the rest:

    In [207]: B[1][:,:,ind].shape
    Out[207]: (3, 4, 5)
    In [208]: B[1][:,:,ind] = np.arange(3*4*5).reshape(3,4,5)
    In [209]: B[1]
    Out[209]: 
    array([[[ 0,  1,  2,  3,  4],
            [ 5,  6,  7,  8,  9],
            [10, 11, 12, 13, 14],
            [15, 16, 17, 18, 19]],
    
           [[20, 21, 22, 23, 24],
            [25, 26, 27, 28, 29],
            [30, 31, 32, 33, 34],
            [35, 36, 37, 38, 39]],
    
           [[40, 41, 42, 43, 44],
            [45, 46, 47, 48, 49],
            [50, 51, 52, 53, 54],
            [55, 56, 57, 58, 59]]])
    

    This only works when that first index is a scalar. If it too were a list (or array), we'd get an intermediate copy, and couldn't set the value like this.

    https://docs.scipy.org/doc/numpy-1.15.0/reference/arrays.indexing.html#combining-advanced-and-basic-indexing

    It's come up in other SO questions, though not recently.

    weird result when using both slice indexing and boolean indexing on a 3d array