1

I have a numpy.array a with the shape (8, 16000, 2) which represents 8 stereo audios each 1s long. I want to sample a 0.5s subsample from each recording. Thus, I sample start and end indices in the following way:

a = np.random.rand(8, 16000, 2)
possible_starts = np.arange(8000)
start_idxs = np.random.choice(possible_starts, size=a.shape[0])
end_idxs = start_idxs + 8000

How to extract these different slices for each row in numpy efficienty? I obviously can do it in loop:

b = np.zeros((8, 8000, 2))
for i in range(a.shape[0]):
    b[i] = a[i, start_idxs[i]: end_idxs[i], :]

but I want to do it in the vectorised way.

Fallen Apart
  • 723
  • 8
  • 20

1 Answers1

1

We can leverage np.lib.stride_tricks.as_strided based scikit-image's view_as_windows to get sliding windowed views and thus solve our problem here in a vectorized way.

from skimage.util.shape import view_as_windows

w = view_as_windows(a, (1,8000,1))[:,:,:,0,:,0]
b_out = w[np.arange(len(start_idxs)), start_idxs].swapaxes(1,2)

Or use np.take_along_axis(w, start_idxs, axis=1).swapaxes(1,2) for better readability as suggested by @Daniel F.

More info on use of as_strided based view_as_windows.

Given that your loop is iterating for just 8 times, you should benchmark.

Divakar
  • 218,885
  • 19
  • 262
  • 358