检查NumPy数组中是否存在值的最有效方法是什么?

时间:2011-08-17 06:13:56

标签: python performance 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
.... 

我想检查一下数组的第一列是否存在值。我有一堆本土方式(例如遍历每一行并检查),但考虑到数组的大小,我想找到最有效的方法。

谢谢!

8 个答案:

答案 0 :(得分:52)

怎么样

if value in my_array[:, col_num]:
    do_whatever

编辑:我认为__contains__的实现方式与@ detly的版本相同

答案 1 :(得分:34)

对我来说最明显的是:

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

答案 2 :(得分:30)

要检查多个值,可以使用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

答案 3 :(得分:11)

魅力。我需要提高一系列循环的速度,这些循环必须以同样的方式执行匹配的索引确定。所以我决定在这里解决所有的解决方案,以及一些riff's。

以下是我对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 array))
  • 15s x in(list)
  • 8s N.any(x == numpy array)
  • 6s x in(numpy array)
  • .1s x in(set or a dictionary)

如果你想知道列表中的某些内容(顺序很重要):

  • 12s N.in1d(x,numpy array)
  • 2s x ==(numpy array)

答案 4 :(得分:1)

添加到@ 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

答案 5 :(得分:0)

我认为最方便的方法是:

//label[@class='m-confirmation-modal-print-detail-capgrey' and contains(.,'Tax')]//following::div[1]/label

其中Val是要检查的值,X是数组。在您的示例中,假设您要检查第三列中是否存在值8。只需写

(Val in X[:, col_num])

如果第三列中有8,则返回True,否则返回False。

答案 6 :(得分:0)

如果您正在寻找整数列表,您可以使用索引来完成这项工作。这也适用于 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 的加速。

答案 7 :(得分:-1)

如果要检查列表a是否在numpy数组b中,请使用以下语法:

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

考虑到numpy数组,放置axis = 1的形状为n*2