6

Python の numpy ライブラリによる派手なインデックス作成の「ベクトル化」は、予期しない結果をもたらすことがあります。例えば:

import numpy
a = numpy.zeros((1000,4), dtype='uint32')
b = numpy.zeros((1000,4), dtype='uint32')
i = numpy.random.random_integers(0,999,1000)
j = numpy.random.random_integers(0,3,1000)

a[i,j] += 1
for k in xrange(1000):
    b[i[k],j[k]] += 1

配列 'a' と 'b' で異なる結果を返します (つまり、タプル (i,j) の出現は、繰り返しに関係なく 'a' では 1 として表示されますが、繰り返しは 'b' でカウントされます)。これは次のように簡単に確認できます。

numpy.sum(a)
883
numpy.sum(b)
1000

また、派手なインデックス作成バージョンは、for ループよりもほぼ 2 桁高速であることも注目に値します。私の質問は次のとおりです。

4

1 に答える 1

6

これはあなたが望むことをするはずです:

np.bincount(np.ravel_multi_index((i, j), (1000, 4)), minlength=4000).reshape(1000, 4)

内訳として、andでravel_multi_index指定されたインデックス ペアを整数インデックスに変換して、C フラット化配列にします。インデックスのリストに各値が出現する回数をカウントします。C フラット化された配列を 2 次元配列に変換します。ijbincount0..4000reshape

パフォーマンスに関しては、「b」の 200 倍、「a」の 5 倍の速度で測定しました。あなたのマイレージは異なる場合があります。

カウントを既存の配列に書き込む必要があるため、aこれを試してください:

u, inv = np.unique(np.ravel_multi_index((i, j), (1000, 4)), return_inverse=True)
a.flat[u] += np.bincount(inv)

この 2 番目の方法は、"a" よりも少し遅く (2 倍) しますが、uniqueステージが遅くなるため、それほど驚くことではありません。

于 2012-06-12T17:03:32.520 に答える