2016-12-21 10 views
4

をスライスするためのより効率的な方法があります私は、多次元配列のインデックスを作成するときにIインデックスa1は多次元配列

%%timeit 
a1[500000] 

a1 = np.arange(1000000) 
a2 = np.arange(1000000).reshape(1000, 1000) 
a3 = np.arange(1000000).reshape(100, 100, 100) 

単一次元配列のインデックスを作成するよりも多くの時間を要することに気づきました

最も遅い実行は、最も速い実行よりも39.17倍長くなりました。これは、中間結果がキャッシュされていることを意味する可能性があります。 3の最良の 10000000ループ、:ループあたり84.6 nsが

%%timeit 
a2[500, 0] 

最も遅い実行が最速よりも31.85倍の時間がかかりました。これは、中間結果がキャッシュされていることを意味する可能性があります。 10000000のループ、3の最高:ループあたり102ナノ秒

%%timeit 
a3[50, 0, 0] 

は最も遅い実行は最速よりも長く46.72倍を取りました。これは、中間結果がキャッシュされていることを意味する可能性があります。 3の最良の 10000000ループ、:どの時点でループ


あたり119 nsが、私は、インデックスの代替方法を検討または多次元配列をスライスする必要がありますか?努力と透明性の欠如に値する状況は何ですか?

+0

スライス( ':')ではなく、個々のアイテムのインデックスを作成する方法について詳しく説明しています。フラット・バージョンでの索引付けは高速ですが、それより少ないファクタでも可能です。速度の向上は明瞭に損失に見合っていますか? 1つのアイテムにインデックスを付ける必要がありますか? – hpaulj

+0

@ hpauljこれは、 "配列とインデックスまたはスライスを平坦化するのに、どのような状況下では価値があるのだろうか? – piRSquared

+1

http://stackoverflow.com/questions/28005531/access-multiple-elements-of-an-array - 2次元配列の各行から複数​​の項目を選択します。フラットなインデックス作成は高速でしたが、インデックスを計算するためのより高いコストとのバランスを取らなければなりませんでした。基本的に同じパターンのパターン - 配列が大きくなるとフラットが良い。 – hpaulj

答えて

5

(n, m)アレイをスライスする代替方法の1つは、アレイを平坦化し、1次元の位置が何であるかを導出することです。

は、我々はa[1, 2]と2列目、3列を取得し、取得し5
または我々は、このように、我々は同等のスライスを行うことができるorder='C'
aを平ら場合、我々は1 * a.shape[1] + 2一次元の位置であることを計算することができa = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
検討しますa.ravel()[1 * a.shape[1] + 2]

これは効率的ですか?いいえ、配列から単一の数値を索引付けする場合、それは問題にはなりません。

アレイから多数の数値をスライスしたい場合はどうなりますか?私は2次元配列


2-Dのテスト

from timeit import timeit 

n, m = 10000, 10000 
a = np.random.rand(n, m) 
r = pd.DataFrame(index=np.power(10, np.arange(7)), columns=['Multi', 'Flat']) 

for k in r.index: 
    b = np.random.randint(n, size=k) 
    c = np.random.randint(m, size=k) 
    kw = dict(setup='from __main__ import a, b, c', number=100) 
    r.loc[k, 'Multi'] = timeit('a[b, c]', **kw) 
    r.loc[k, 'Flat'] = timeit('a.ravel()[b * a.shape[1] + c]', **kw) 

r.div(r.sum(1), 0).plot.bar() 

enter image description here

にするために、次のテストを考案10万個の以上の数字をスライスするとき、それは良いでしょうと思われます配列を平坦化します。


3-D
3-Dのテスト

from timeit import timeit 

l, n, m = 1000, 1000, 1000 
a = np.random.rand(l, n, m) 
r = pd.DataFrame(index=np.power(10, np.arange(7)), columns=['Multi', 'Flat']) 

for k in r.index: 
    b = np.random.randint(l, size=k) 
    c = np.random.randint(m, size=k) 
    d = np.random.randint(n, size=k) 

    kw = dict(setup='from __main__ import a, b, c, d', number=100) 
    r.loc[k, 'Multi'] = timeit('a[b, c, d]', **kw) 
    r.loc[k, 'Flat'] = timeit('a.ravel()[b * a.shape[1] * a.shape[2] + c * a.shape[1] + d]', **kw) 

r.div(r.sum(1), 0).plot.bar() 

enter image description here

についても同様の結果、多分もっと劇的な。 2次元配列の場合

結論
、平坦化して、配列から10万個の以上の要素をプルする必要がある場合は、位置を平らに導き出すことを検討してください。

3次元以上の場合、配列の平坦化はほとんど常に優れているようです。


批判が
私が何か間違ったことをしました歓迎ですか?私は何か明白ではないと思ったのですか?

+0

一見したところ、計算はよく見えます。興味深いことに、スピードの優位性は一定のままです。私はこれにいくつかのユースケースがあると思います。 –

+0

私はそれを感謝します。 – piRSquared