4

1D numpy配列と、いくつかのオフセット/長さの値があります。この配列から、offset、offset + length内にあるすべてのエントリを抽出します。これらのエントリは、元の配列から新しい「reduced」配列を構築するために使用されます。この配列は、offset/lengthのペアによって選択された値のみで構成されます。 。

単一のオフセット/長さのペアの場合、これは標準のアレイスライスでは簡単[offset:offset+length]です。しかし、多くのオフセット/長さの値に対してこれを効率的に(つまりループなしで)行うにはどうすればよいですか?

ありがとう、マーク

4

2 に答える 2

6
>>> 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])
于 2012-06-16T08:51:53.747 に答える
5

単純な方法があります。スライスを行うだけです:

>>> 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

これは、間隔が少ない場合は最初の方法が最も高速であり (さらに大幅に高速である)、間隔が多い場合は 2 番目の方法が最も高速であることを示しています。

于 2012-06-16T08:54:17.720 に答える