Вы не можете сказать скомпилированному numpy
, чтобы он брал несколько кусков напрямую.Альтернативы объединению нескольких секций включают в себя некоторую расширенную индексацию.
In [509]: a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
...:
...: sindex = np.array([0, 3, 4])
...: eindex = np.array([2, 5, 6])
Наиболее очевидный цикл:
In [511]: np.hstack([a[i:j] for i,j in zip(sindex, eindex)])
Out[511]: array([1, 2, 4, 5, 5, 6])
Вариант, который сначала использует цикл для создания индексов:
In [516]: a[np.hstack([np.arange(i,j) for i,j in zip(sindex, eindex)])]
Out[516]: array([1, 2, 4, 5, 5, 6])
Поскольку размер среза одинаков, мы можем сгенерировать один arange
и сделать шаг с помощью sindex
:
In [521]: a[np.arange(eindex[0]-sindex[0]) + sindex[:,None]]
Out[521]:
array([[1, 2],
[4, 5],
[5, 6]])
, а затем ravel
.Это более прямое выражение @Divakar's
broadcasting_app`.
В этом небольшом примере время аналогично.
In [532]: timeit np.hstack([a[i:j] for i,j in zip(sindex, eindex)])
13.4 µs ± 257 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [533]: timeit a[np.hstack([np.arange(i,j) for i,j in zip(sindex, eindex)])]
21.2 µs ± 362 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [534]: timeit a[np.arange(eindex[0]-sindex[0])+sindex[:,None]].ravel()
10.1 µs ± 48.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [535]: timeit strided_app(a, L=2, S=1)[sindex].ravel()
21.8 µs ± 207 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
strided_app
и view_as_windows
используют пошаговые трюки, чтобы просмотреть массив как массив размером d
окон, и использовать sindex
, чтобы выбрать их подмножество.
В более крупных случаях относительное время может варьироваться в зависимости от размера срезов в зависимости от количества срезов.