用数组切片数组

时间:2019-05-05 12:43:13

标签: python-3.x numpy

我知道这个问题已经回答了很多次,因此我就此主题回答了每个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 个答案:

答案 0 :(得分:2)

对于恒定的间隔差,我们可以设置滑动窗口,并简单地使用起始索引数组进行索引。因此,我们可以使用this post-

中的broadcasting_appstrided_app
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 built-in 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 :(得分:1)

您不能告诉编译后的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_appview_as_windows使用步进技巧将数组视为大小为d的窗口数组,并使用sindex选择其中的一个子集。

在较大的情况下,相对时间可能会随着切片的大小与切片的数量而变化。

答案 2 :(得分:0)

您可以只使用sindex。请参考下图

enter image description here