Нарезка массива с массивами - PullRequest
1 голос
/ 05 мая 2019

Я знаю, что на это отвечали много раз, и я прошел каждый SO вопрос по этой теме, но ни один из них, казалось, не решал мою проблему.

Этот код выдает исключение:

TypeError: only integer scalar arrays can be converted to a scalar index
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])

sindex = np.array([0, 3, 4])
eindex = np.array([2, 5, 6])

r = a[sindex: eindex]

У меня есть массив с начальными индексами и еще один с конечными индексами, и я просто хотел извлечь то, что находится между ними. Обратите внимание, что разница между sindex и eindex постоянна, например, 2. Таким образом, eindex всегда равен тому, что есть в sindex + 2.

Итак, ожидаемый результат должен быть:

[1, 2, 4, 5, 5, 6]

Есть ли способ сделать это без цикла for?

Ответы [ 3 ]

2 голосов
/ 05 мая 2019

Для постоянной разницы интервалов мы можем настроить скользящие окна и просто индексировать с помощью массива начальных индексов. Таким образом, мы можем использовать broadcasting_app или strided_app из this post -

d = 2  # interval difference

out = broadcasting_app(a, L = d, S = 1)[sindex].ravel()

out = strided_app(a, L = d, S = 1)[sindex].ravel()

Или используйте scikit-image's встроенный view_as_windows -

from skimage.util.shape import view_as_windows

out = view_as_windows(a,d)[sindex].ravel()

Чтобы установить d, мы можем использовать -

d = eindex[0] - sindex[0]
1 голос
/ 05 мая 2019

Вы не можете сказать скомпилированному 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, чтобы выбрать их подмножество.

В более крупных случаях относительное время может варьироваться в зависимости от размера срезов в зависимости от количества срезов.

0 голосов
/ 05 мая 2019

Вы можете просто использовать sindex.См. Следующее изображение

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...