10

スライスを取り除く必要がある整数の大きな 1 次元配列があります。それは些細なことですa[start:end]。問題は、これらのスライスがもっと必要なことです。a[start:end]start と end が配列の場合は機能しません。これには for ループを使用できますが、可能な限り高速にする必要があるため (ボトルネックです)、ネイティブの numpy ソリューションを歓迎します。

さらに説明するために、私はこれを持っています:

a = numpy.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], numpy.int16)
start = numpy.array([1, 5, 7], numpy.int16)
end   = numpy.array([2, 10, 9], numpy.int16)

そして、どういうわけかこれにする必要があります:

[[1], [5, 6, 7, 8, 9], [7, 8]] 
4

5 に答える 5

9

numpyこれは(ほぼ?)マスクされた配列とストライドトリックを使用して純粋に行うことができます。まず、マスクを作成します。

>>> indices = numpy.arange(a.size)
>>> mask = ~((indices >= start[:,None]) & (indices < end[:,None]))

またはもっと簡単に:

>>> mask = (indices < start[:,None]) | (indices >= end[:,None])

マスクは、開始値と終了値Falseに対するインデックスに対して(つまり、マスクされていない値)です。( (aka )でスライスすると、新しい次元が追加され、ブロードキャストが可能になります。)これで、マスクは次のようになります。>=<Nonenumpy.newaxis

>>> mask
array([[ True, False,  True,  True,  True,  True,  True,  True,  True,
         True,  True,  True],
       [ True,  True,  True,  True,  True, False, False, False, False,
        False,  True,  True],
       [ True,  True,  True,  True,  True,  True,  True, False, False,
         True,  True,  True]], dtype=bool)

次に、次を使用して、マスクに合うように配列をストレッチする必要がありますstride_tricks

>>> as_strided = numpy.lib.stride_tricks.as_strided
>>> strided = as_strided(a, mask.shape, (0, a.strides[0]))
>>> strided
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
       [ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
       [ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11]], dtype=int16)

これは3x12配列のように見えますが、各行は同じメモリを指しています。これで、それらを組み合わせてマスクされた配列にすることができます。

>>> numpy.ma.array(strided, mask=mask)
masked_array(data =
 [[-- 1 -- -- -- -- -- -- -- -- -- --]
 [-- -- -- -- -- 5 6 7 8 9 -- --]
 [-- -- -- -- -- -- -- 7 8 -- -- --]],
             mask =
 [[ True False  True  True  True  True  True  True  True  True  True  True]
 [ True  True  True  True  True False False False False False  True  True]
 [ True  True  True  True  True  True  True False False  True  True  True]],
       fill_value = 999999)

これはあなたが求めたものとはまったく同じではありませんが、同じように動作するはずです。

于 2012-09-25T20:58:58.577 に答える
6

これを行うための厄介な方法はありません。不規則なので、とにかく配列/スライスのリストにすぎないことに注意してください。ufuncsただし、numpyのほとんどすべての関数である(または少なくともそれらに基づいている)すべての(バイナリ)reduceatに対して、実際にスライスのリストを作成することを回避するのに役立つ可能性のあるメソッドがあります。 、スライスが小さい場合は、計算も高速化します。

In [1]: a = np.arange(10)

In [2]: np.add.reduceat(a, [0,4,7]) # add up 0:4, 4:7 and 7:end
Out[2]: array([ 6, 15, 24])

In [3]: np.maximum.reduceat(a, [0,4,7]) # maximum of each of those slices
Out[3]: array([3, 6, 9])

In [4]: w = np.asarray([0,4,7,10]) # 10 for the total length

In [5]: np.add.reduceat(a, w[:-1]).astype(float)/np.diff(w) # equivalent to mean
Out[5]: array([ 1.5,  5. ,  8. ])

編集:あなたのスライスが重なっているので、これもOKだと付け加えます:

# I assume that start is sorted for performance reasons.
reductions = np.column_stack((start, end)).ravel()
sums = np.add.reduceat(a, reductions)[::2]

重複するスライスに対して実際の余分な作業は行われないため、通常、ここ[::2]では大したことはありません。

また、ここでスライスに1つの問題がありstop==len(a)ます。これは避ける必要があります。スライスが1つしかない場合は、(最後のスライスの場合)実行できますが、それ以外の場合は、トリックreductions = reductions[:-1]に値を追加する必要があります。areduceat

 a = np.concatenate((a, [0]))

とにかくスライスで作業するので、最後に1つの値を追加することは重要ではありません。

于 2012-09-25T20:29:32.153 に答える
1

これは「純粋な」numpy ソリューションではありません (ただし、@mgilson のコメントにあるように、不規則な出力が numpy 配列になる方法を理解するのは困難です)。

a = numpy.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], numpy.int16)
start = numpy.array([1, 5, 7], numpy.int16)
end   = numpy.array([2, 10, 9], numpy.int16)

map(lambda range: a[range[0]:range[1]],zip(start,end))

あなたを取得します:

[array([1], dtype=int16), array([5, 6, 7, 8, 9], dtype=int16),  array([7, 8], dtype=int16)]

要求に応じ。

于 2012-09-25T19:50:37.090 に答える
1

1 行で表示する場合は、次のようになります。

x=[list(a[s:e]) for (s,e) in zip(start,end)]
于 2016-05-30T19:47:12.127 に答える
0

timday のような同様のソリューション。同様の速度:

a = np.random.randint(0,20,1e6)
start = np.random.randint(0,20,1e4)
end = np.random.randint(0,20,1e4)

def my_fun(arr,start,end):
        return arr[start:end]

%timeit [my_fun(a,i[0],i[1]) for i in zip(start,end)]
%timeit map(lambda range: a[range[0]:range[1]],zip(start,end))

100 loops, best of 3: 7.06 ms per loop 100 loops, best of 3: 6.87 ms per loop

于 2015-05-25T12:10:35.170 に答える