Fancy indexing for numpy arrary

Viewed 52

I want to sample len(valid_frame_id_ls) frame from data by fancy indexing for numpy arrary. But I received an error message when i run code1. I don't know why the shape of data[n, :, valid_frame_id_ls, :, :] is not equal to the shape of new_data[n, :, :len(valid_frame_id_ls), :, :].Can anyone help me solve this bug. help...

I modify my code and write in code2 block. I did't receive any error message when i run code2. I don't know why code2 is correct.

code1:


    data = np.random.random((2, 3, 50, 25, 1))
    N, C, T, V, M = data.shape
    new_data = np.zeros((N, C, T, V, M))
    valid_frame_id_ls = [2, 3, 4, 5, 6]
    for n in range(N):
        new_data[n, :, :len(valid_frame_id_ls), :, :] = data[n, :, valid_frame_id_ls, :, :]
# code1 error message:
    new_data[n, :, :len(valid_frame_id_ls), :, :] = data[n, :, valid_frame_id_ls, :, :]
ValueError: could not broadcast input array from shape (5,3,25,1) into shape (3,5,25,1)

code2:

    data = np.random.random((2, 3, 50, 25, 1))
    N, C, T, V, M = data.shape
    new_data = np.zeros((N, C, T, V, M))
    valid_frame_id_ls = [2, 3, 4, 5, 11]
    for n in range(N):
        new_data[n][:, :len(valid_frame_id_ls), :, :] = data[n][ :, valid_frame_id_ls, :, :]
1 Answers

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

As described in this section of the docs, putting a slice in the middle of 'advanced' indexing results in an unexpected rearrangement of dimensions. Your size 5 dimension has been placed first, and the other dimensions after.

This has come up occasionally on SO as well. With a scalar n this really shouldn't be happening, but apparently the issue occurs deep in the indexing, and isn't easily corrected.

data[n][ :, valid_frame_id_ls, :, :]

breaks up the indexing, so the first ':' is no longer in the middle.

Another fix is to replace the slice with an equivalent array. Now both sides will have the same dimensions.

new_data[n, :, np.arange(len(valid_frame_id_ls)), :, :] = data[n, :, valid_frame_id_ls, :, :]

Though in this case I don't think you need to iterate on N at all:

new_data[:,:,:len(valid_frame_id_ls),:,:] = data[:,:, valid_frame_id_ls, :,:]
Related