簡體   English   中英

檢查 NumPy 數組中是否存在值的最有效方法是什么?

[英]What is the most efficient way to check if a value exists in a NumPy array?

我有一個非常大的 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
.... 

我想檢查數組的第一列中是否存在值。 我有很多本土方法(例如遍歷每一行並檢查),但考慮到數組的大小,我想找到最有效的方法。

謝謝!

怎么樣

if value in my_array[:, col_num]:
    do_whatever

編輯:我認為__contains__的實現方式與@detly 的版本相同

對我來說最明顯的是:

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

To check multiple values, you can use numpy.in1d(), which is an element-wise function version of the python keyword in. If your data is sorted, you can use 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

迷人。 我需要提高必須以相同方式執行匹配索引確定的一系列循環的速度。 所以我決定在這里計算所有解決方案的時間,以及一些即興演奏。

這是我對 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

非常令人驚訝! 數量級差異!

總而言之,如果您只想知道某物是否在一維列表中:

  • 19s N.any(N.in1d(numpy 數組))
  • 15s x in (列表)
  • 8s N.any(x == numpy 陣列)
  • 6s x in (numpy 數組)
  • .1s x in(集合或字典)

如果您還想知道列表中的某些內容(順序很重要):

  • 12s N.in1d(x, numpy 陣列)
  • 2s x == (numpy 數組)

對於 numpy,添加到@HYRY 的答案 in1d 似乎是最快的。 這是使用 numpy 1.8 和 python 2.7.6。

在這個測試中 in1d 是最快的,但是10 in a看起來更干凈:

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

構造一個集合比調用 in1d,但是檢查值是否存在要快一點:

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

10000000 loops, best of 3: 47 ns per loop

據我所知,最方便的方法是:

(Val in X[:, col_num])

其中 Val 是您要檢查的值, X 是數組。 在您的示例中,假設您要檢查值 8 是否存在於您的第三列中。 簡單地寫

(8 in X[:, 2])

如果第三列中有 8,這將返回 True,否則返回 False。

如果您正在尋找整數列表,您可以使用索引來完成這項工作。 這也適用於 nd-arrays,但似乎更慢。 不止一次這樣做可能會更好。

def valuesInArray(values, array):
    values = np.asanyarray(values)
    array = np.asanyarray(array)
    assert array.dtype == np.int and values.dtype == np.int
    
    matches = np.zeros(array.max()+1, dtype=np.bool_)
    matches[values] = True
    
    res = matches[array]
    
    return np.any(res), res
    
    
array = np.random.randint(0, 1000, (10000,3))
values = np.array((1,6,23,543,222))

matched, matches = valuesInArray(values, array)

通過使用 numba 和 njit,我可以將這個速度提高 ~x10。

如果要檢查列表a是否在 numpy 數組b中,請使用以下語法:

np.any(np.equal(a, b).all(axis=1))

考慮到 numpy 陣列的形狀為n*2 ,放置axis = 1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM