6

配列があるとします

import numpy as np
x=np.array([5,7,2])

x で指定された各範囲の長さと一緒に積み重ねられた一連の範囲を含む配列を作成したいと考えています。

y=np.hstack([np.arange(1,n+1) for n in x])

リストの理解やループの速度の低下なしにこれを行う方法はありますか? (x は非常に大きな配列になる可能性があります)

結果は

y == np.array([1,2,3,4,5,1,2,3,4,5,6,7,1,2])
4

2 に答える 2

5

蓄積を使用できます:

def my_sequences(x):
    x = x[x != 0] # you can skip this if you do not have 0s in x.

    # Create result array, filled with ones:
    y = np.cumsum(x, dtype=np.intp)
    a = np.ones(y[-1], dtype=np.intp)

    # Set all beginnings to - previous length:
    a[y[:-1]] -= x[:-1]

    # and just add it all up (btw. np.add.accumulate is equivalent):
    return np.cumsum(a, out=a) # here, in-place should be safe.

(注意: 結果の配列が可能なサイズよりも大きくなる場合、np.iinfo(np.intp).max運が悪いと、きれいにエラーになるのではなく、間違った結果が返される可能性があります...)

そして、誰もが常に(Ophionの方法と比較して)タイミングを望んでいるため:

In [11]: x = np.random.randint(0, 20, 1000000)

In [12]: %timeit ua,uind=np.unique(x,return_inverse=True);a=[np.arange(1,k+1) for k in ua];np.concatenate(np.take(a,uind))
1 loops, best of 3: 753 ms per loop

In [13]: %timeit my_sequences(x)
1 loops, best of 3: 191 ms per loop

もちろん、の値が大きくなってもmy_sequences関数のパフォーマンスが低下することはありません。x

于 2013-08-06T18:18:49.870 に答える
4

最初のアイデア; への複数の呼び出しを防ぎnp.arange、次のconcatenate場合よりもはるかに高速になるはずhstackです。

import numpy as np
x=np.array([5,7,2])

>>>a=np.arange(1,x.max()+1)
>>> np.hstack([a[:k] for k in x])
array([1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 7, 1, 2])

>>> np.concatenate([a[:k] for k in x])
array([1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 7, 1, 2])

一意でない値が多数ある場合、これはより効率的と思われます。

>>>ua,uind=np.unique(x,return_inverse=True)
>>>a=[np.arange(1,k+1) for k in ua]
>>>np.concatenate(np.take(a,uind))

array([1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 7, 1, 2])

あなたの場合のいくつかのタイミング:

x=np.random.randint(0,20,1000000) 

元のコード

#Using hstack
%timeit np.hstack([np.arange(1,n+1) for n in x])
1 loops, best of 3: 7.46 s per loop

#Using concatenate
%timeit np.concatenate([np.arange(1,n+1) for n in x])
1 loops, best of 3: 5.27 s per loop

最初のコード:

#Using hstack
%timeit a=np.arange(1,x.max()+1);np.hstack([a[:k] for k in x])
1 loops, best of 3: 3.03 s per loop

#Using concatenate
%timeit a=np.arange(1,x.max()+1);np.concatenate([a[:k] for k in x])
10 loops, best of 3: 998 ms per loop

2 番目のコード:

%timeit ua,uind=np.unique(x,return_inverse=True);a=[np.arange(1,k+1) for k in ua];np.concatenate(np.take(a,uind))
10 loops, best of 3: 522 ms per loop

最終的なコードで 14 倍のスピードアップが得られたようです。

小さな健全性チェック:

ua,uind=np.unique(x,return_inverse=True)
a=[np.arange(1,k+1) for k in ua]
out=np.concatenate(np.take(a,uind))

>>>out.shape
(9498409,)

>>>np.sum(x)
9498409
于 2013-08-06T15:43:06.337 に答える