我有一个 1D numpy 数组和一些偏移量/长度值。我想从这个数组中提取所有属于偏移量、偏移量+长度的条目,然后用于从原始数组构建一个新的“缩减”数组,该数组只包含偏移量/长度对选择的那些值.
对于单个偏移量/长度对,这对于标准数组切片来说是微不足道的[offset:offset+length]
。但是对于许多偏移量/长度值,我怎样才能有效地做到这一点(即没有任何循环)?
谢谢,马克
>>> 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])
有朴素的方法;只是做切片:
>>> 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])
目前尚不清楚这是否真的比天真的方法更快,但如果你有很多非常短的时间间隔,它可能会更快。但我不知道。
(这最后一种方法与@fraxel 的解决方案基本相同,只是使用了不同的制作索引列表的方法。)
我测试了几种不同的情况:一些短间隔,一些长间隔,很多短间隔。我使用了以下脚本:
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
这表明我的第一种方法在您有几个间隔时是最快的(并且它明显更快),而我的第二种方法在您有很多间隔时是最快的。