web-dev-qa-db-ja.com

NumPy配列に値が存在するかどうかを確認する最も効率的な方法は何ですか?

私は非常に大きなNumPy配列を持っています

1 40 3
4 50 4
5 60 7
5 49 6
6 70 8
8 80 9
8 72 1
9 90 7
.... 

配列の1列目に値が存在するかどうかを確認したい。独自の方法(たとえば、各行を繰り返し処理して確認する方法)がたくさんありますが、配列のサイズを考えると、最も効率的な方法を見つけたいと思います。

ありがとう!

49
thegreatt

どう?

if value in my_array[:, col_num]:
    do_whatever

編集:__contains__は、これが@detlyのバージョンと同じになるように実装されます

60
agf

私にとって最も明白なことは次のとおりです。

np.any(my_array[:, 0] == value)
37
detly

複数の値を確認するには、numpy.in1d()を使用できます。これは、pythonキーワード入力の要素単位の関数バージョンです。データがソートされている場合は、numpy.searchsorted( ):

import numpy as np
data = np.array([1,4,5,5,6,8,8,9])
values = [2,3,4,6,7]
print np.in1d(values, data)

index = np.searchsorted(data, values)
print data[index] == values
31
HYRY

魅力的です。これと同じ方法で一致するインデックスの決定を実行する必要がある一連のループの速度を改善する必要がありました。そこで、ここですべてのソリューションと、いくつかのリフの時間を決定することにしました。

Python 2.7.10の速度テストは次のとおりです。

import timeit
timeit.timeit('N.any(N.in1d(sids, val))', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

18.86137104034424

timeit.timeit('val in sids', setup = 'import numpy as N; val = 20010401020091; sids = [20010401010101+x for x in range(1000)]')

15.061666011810303

timeit.timeit('N.in1d(sids, val)', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

11.613027095794678

timeit.timeit('N.any(val == sids)', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

7.670552015304565

timeit.timeit('val in sids', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

5.610057830810547

timeit.timeit('val == sids', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

1.6632978916168213

timeit.timeit('val in sids', setup = 'import numpy as N; val = 20010401020091; sids = set([20010401010101+x for x in range(1000)])')

0.0548710823059082

timeit.timeit('val in sids', setup = 'import numpy as N; val = 20010401020091; sids = dict(Zip([20010401010101+x for x in range(1000)],[True,]*1000))')

0.054754018783569336

非常に驚くべき!桁違いの違い!

要約すると、何かが1Dリストにあるかどうかだけを知りたい場合:

  • 19s N.any(N.in1d(numpy array))
  • 15秒x(リスト)
  • 8s N.any(x == numpy配列)
  • 6s x in(numpy配列)
  • .1s x in(セットまたは辞書)

リスト内の何かも知りたい場合(順序が重要です):

  • 12s N.in1d(x、numpy配列)
  • 2s x ==(numpy配列)
11
Lukas Mandrake

@HYRYの答えin1dに追加することは、numpyにとって最速のようです。これは、numpy 1.8とpython 2.7.6。

このテストでは、in1dが最速でした:

a = arange(0,99999,3)
%timeit 10 in a
%timeit in1d(a, 10)

10000 loops, best of 3: 150 µs per loop
10000 loops, best of 3: 61.9 µs per loop

Pythonセットを使用するのが最も速いようです:

s = set(range(0, 99999, 3))
%timeit 10 in s

10000000 loops, best of 3: 47 ns per loop
1
Joelmob

私によると、最も便利な方法は次のとおりです。

(Val in X[:, col_num])

ここで、Valは確認する値、Xは配列です。この例では、3列目に値8が存在するかどうかを確認するとします。単に書く

(8 in X[:, 2])

3番目の列に8があればTrueを返し、そうでなければFalseを返します。

0
Loochie