NumPy的数组分片(Numpy Array Slicing)

2019-06-25 13:23发布

我有一个一维阵列numpy的,和一些偏移/长度的值。 我想从这个数组中提取落入内的偏移的所有条目,偏移+长度,然后将其用于建立与原始一个新的“降低的”数组,即仅由由偏移/长度对拾取这些值的。

对于单个偏移/长度对,这是微不足道的标准阵列切片[offset:offset+length] 。 但是,我怎么能做到这一点有效(即没有任何环路)对许多偏移/长度值?

谢谢,马克

Answer 1:

有朴素方法; 只是在做切片:

>>> import numpy as np
>>> a = np.arange(100)
>>> 
>>> offset_length = [(3,10),(50,3),(60,20),(95,1)]
>>>
>>> np.concatenate([a[offset:offset+length] for offset,length in offset_length])
array([ 3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 50, 51, 52, 60, 61, 62, 63,
       64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 95])

下面可能更快,但你必须要测试/基准。

它的工作原理通过构建所期望的指数列表,这是一个索引阵列numpy的有效方法。

>>> indices = [offset + i for offset,length in offset_length for i in xrange(length)]
>>> a[indices]
array([ 3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 50, 51, 52, 60, 61, 62, 63,
       64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 95])

目前尚不清楚这是否会实际上可能比天真的方法更快,但如果你有很多很短的时间间隔可能是。 但我不知道。

(这最后一种方法是基本相同@飞梭的解决方案,只是用做索引列表不同的方法。)


性能测试

我测试了几个不同的情况:在短短的时间间隔,几个长的时间间隔,许多短的间隔。 我用下面的脚本:

import timeit

setup = 'import numpy as np; a = np.arange(1000); offset_length = %s'

for title, ol in [('few short', '[(3,10),(50,3),(60,10),(95,1)]'),
                  ('few long', '[(3,100),(200,200),(600,300)]'),
                  ('many short', '[(2*x,1) for x in range(400)]')]:
  print '**',title,'**'
  print 'dbaupp 1st:', timeit.timeit('np.concatenate([a[offset:offset+length] for offset,length in offset_length])', setup % ol, number=10000)
  print 'dbaupp 2nd:', timeit.timeit('a[[offset + i for offset,length in offset_length for i in xrange(length)]]', setup % ol, number=10000)
  print '    fraxel:', timeit.timeit('a[np.concatenate([np.arange(offset,offset+length) for offset,length in offset_length])]', setup % ol, number=10000)

这种输出:

** few short **
dbaupp 1st: 0.0474979877472
dbaupp 2nd: 0.190793991089
    fraxel: 0.128381967545
** few long **
dbaupp 1st: 0.0416231155396
dbaupp 2nd: 1.58000087738
    fraxel: 0.228138923645
** many short **
dbaupp 1st: 3.97210478783
dbaupp 2nd: 2.73584890366
    fraxel: 7.34302687645

这表明,我的第一个方法是最快的,当你有几个区间(它是显著更快),和我的第二个是最快的,当你有很多的时间间隔。



Answer 2:

>>> import numpy as np
>>> a = np.arange(100)
>>> ind = np.concatenate((np.arange(5),np.arange(10,15),np.arange(20,30,2),np.array([8])))
>>> a[[ind]]
array([ 0,  1,  2,  3,  4, 10, 11, 12, 13, 14, 20, 22, 24, 26, 28,  8])


文章来源: Numpy Array Slicing