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

the*_*att 51 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
.... 
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

agf*_*agf 62

怎么样

if value in my_array[:, col_num]:
    do_whatever
Run Code Online (Sandbox Code Playgroud)

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

  • 你知道,我最近一直在使用`numpy`的`any()`函数,我完全忘记了简单的`in`. (8认同)
  • 好的,这是(a)更具可读性,(b)比我的答案快40%左右. (8认同)
  • 原则上,`value in ...`可以比`any(... == value)`更快,因为它可以迭代数组元素并在遇到值时停止(而不是计算每个数组元素是否等于value,然后检查其中一个布尔结果是否为true). (4认同)
  • 事情发生了变化,请注意,将来@ detly的答案将成为唯一可行的解​​决方案,目前会发出警告.有关更多信息,请参阅/sf/ask/2846144871/. (3认同)

det*_*tly 37

对我来说最明显的是:

np.any(my_array[:, 0] == value)
Run Code Online (Sandbox Code Playgroud)

  • @jameshwartlopez `my_array[:, 0]` 为您提供所有行(用 `:` 表示)以及每行的第 `0` 个元素,即第一列。这是一个简单的一维数组,例如“[1, 3, 6, 2, 9]”。如果您在 numpy 中将 == 运算符与标量一起使用,它将进行逐元素比较并返回与数组形状相同的布尔 numpy 数组。所以 `[1, 3, 6, 2, 9] == 3` 给出 `[False, True, False, False, False]`。最后,“np.any”检查该数组中的任何值是否为“True”。 (4认同)
  • HI @detly可以添加更多解释.这对你来说似乎很明显,但像我这样的初学者却不是.我的直觉告诉我,这可能是我正在寻找的解决方案,但我无法用例子来尝试:D (2认同)

HYR*_*YRY 33

要检查多个值,可以使用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
Run Code Online (Sandbox Code Playgroud)

  • +1为不太知名的`numpy.in1d()`和非常快的`searchsorted()`. (3认同)

小智 13

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

以下是我对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)])')
Run Code Online (Sandbox Code Playgroud)

18.86137104034424

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

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)])')
Run Code Online (Sandbox Code Playgroud)

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)])')
Run Code Online (Sandbox Code Playgroud)

7.670552015304565

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

5.610057830810547

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

1.6632978916168213

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

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))')
Run Code Online (Sandbox Code Playgroud)

0.054754018783569336

非常令人惊讶!数量级差异的订单!

总而言之,如果您只是想知道某个列表中是否存在某些内容:

  • 19s N.any(N.in1d(numpy array))
  • 15s x in(list)
  • 8s N.any(x == numpy数组)
  • 6s x in(numpy数组)
  • .1s x in(set或a dictionary)

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

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