numpy 配列をスパース辞書にできるだけ早く変換することに興味があります。詳しく説明しましょう:
配列を考えると:
numpy.array([12,0,0,0,3,0,0,1])
辞書を作成したい:
{0:12, 4:3, 7:1}
ご覧のとおり、シーケンス型を非ゼロのインデックスからその値への明示的なマッピングに変換しているだけです。
これをもう少し面白くするために、代替手段を試すために次のテスト ハーネスを提供します。
from timeit import Timer
if __name__ == "__main__":
s = "import numpy; from itertools import izip; from numpy import nonzero, flatnonzero; vector = numpy.random.poisson(0.1, size=10000);"
ms = [ "f = flatnonzero(vector); dict( zip( f, vector[f] ) )"
, "f = flatnonzero(vector); dict( izip( f, vector[f] ) )"
, "f = nonzero(vector); dict( izip( f[0], vector[f] ) )"
, "n = vector > 0; i = numpy.arange(len(vector))[n]; v = vector[n]; dict(izip(i,v))"
, "i = flatnonzero(vector); v = vector[vector > 0]; dict(izip(i,v))"
, "dict( zip( flatnonzero(vector), vector[flatnonzero(vector)] ) )"
, "dict( zip( flatnonzero(vector), vector[nonzero(vector)] ) )"
, "dict( (i, x) for i,x in enumerate(vector) if x > 0);"
]
for m in ms:
print " %.2fs" % Timer(m, s).timeit(1000), m
ポアソン分布を使用して、変換したい配列の種類をシミュレートしています。
これまでの私の結果は次のとおりです。
0.78s f = flatnonzero(vector); dict( zip( f, vector[f] ) )
0.73s f = flatnonzero(vector); dict( izip( f, vector[f] ) )
0.71s f = nonzero(vector); dict( izip( f[0], vector[f] ) )
0.67s n = vector > 0; i = numpy.arange(len(vector))[n]; v = vector[n]; dict(izip(i,v))
0.81s i = flatnonzero(vector); v = vector[vector > 0]; dict(izip(i,v))
1.01s dict( zip( flatnonzero(vector), vector[flatnonzero(vector)] ) )
1.03s dict( zip( flatnonzero(vector), vector[nonzero(vector)] ) )
4.90s dict( (i, x) for i,x in enumerate(vector) if x > 0);
ご覧のとおり、私が見つけた最速の解決策は
n = vector > 0;
i = numpy.arange(len(vector))[n]
v = vector[n]
dict(izip(i,v))
より速い方法はありますか?
編集:ステップ
i = numpy.arange(len(vector))[n]
一部の要素のみを選択する前に配列全体を生成するのは特に不器用に思えます。特に、選択される要素の約 1/10 しかないことがわかっている場合はそうです。これはまだ改善される可能性があると思います。