是一组数组的元素?

gbo*_*ffi 6 python numpy

import numpy
data = numpy.random.randint(0, 10, (6,8))
test = set(numpy.random.randint(0, 10, 5))
Run Code Online (Sandbox Code Playgroud)

我想要一个表达式,其值是一个布尔数组,具有相同的形状data(或者,至少可以重新整形为相同的形状),告诉我相应的术语data是否在set.

例如,如果我想知道哪些元素data严格小于6,我可以使用单个矢量化表达式,

a = data < 6
Run Code Online (Sandbox Code Playgroud)

计算6x8布尔ndarray.相反,当我尝试一个明显等效的布尔表达式时

b = data in test
Run Code Online (Sandbox Code Playgroud)

我得到的是一个例外:

TypeError: unhashable type: 'numpy.ndarray'
Run Code Online (Sandbox Code Playgroud)

附录 - 提供不同的解决方案

编辑:下面的可能性#4给出了错误的结果,感谢hpaulj和Divakar让我走上正轨.

在这里我比较四种不同的可能性

  1. Divakar提出的建议,np.in1d(data, np.hstack(test)).
  2. hpaulj提出的一项提案,np.in1d(data, np.array(list(test))).
  3. hpaulj的另一个提议,`np.in1d(data,np.fromiter(test,int)).
  4. 在其作者删除的答案中提出的建议,其名称我不记得了,np.in1d(data, test).

这是Ipython会话,略微编辑以避免空行

In [1]: import numpy as np
In [2]: nr, nc = 100, 100
In [3]: top = 3000
In [4]: data = np.random.randint(0, top, (nr, nc))
In [5]: test = set(np.random.randint(0, top, top//3))
In [6]: %timeit np.in1d(data, np.hstack(test))
100 loops, best of 3: 5.65 ms per loop
In [7]: %timeit np.in1d(data, np.array(list(test)))
1000 loops, best of 3: 1.4 ms per loop
In [8]: %timeit np.in1d(data, np.fromiter(test, int))
1000 loops, best of 3: 1.33 ms per loop
Run Code Online (Sandbox Code Playgroud)

In [9]: %timeit np.in1d(data, test)
1000 loops, best of 3: 687 µs per loop

In [10]: nr, nc = 1000, 1000
In [11]: top = 300000
In [12]: data = np.random.randint(0, top, (nr, nc))
In [13]: test = set(np.random.randint(0, top, top//3))
In [14]: %timeit np.in1d(data, np.hstack(test))
1 loop, best of 3: 706 ms per loop
In [15]: %timeit np.in1d(data, np.array(list(test)))
1 loop, best of 3: 269 ms per loop
In [16]: %timeit np.in1d(data, np.fromiter(test, int))
1 loop, best of 3: 274 ms per loop
Run Code Online (Sandbox Code Playgroud)

In [17]: %timeit np.in1d(data, test)
10 loops, best of 3: 67.9 ms per loop

In [18]: 
Run Code Online (Sandbox Code Playgroud)

(现在)匿名海报的回答给出了更好的时间.

事实证明,匿名海报有充分理由删除他们的答案,结果是错误的!

正如hpaulj所评论的,在文档中in1d有一个警告,反对使用a set作为第二个参数,但如果计算结果可能是错误的,我会更好地明确失败.

也就是说,使用的解决方案numpy.fromiter()具有最佳数字......

Div*_*kar 6

我假设您正在寻找一个布尔数组来检测数组中set元素的存在data.要做到这一点,就可以提取从元件setnp.hstack,然后使用np.in1d检测的存在任何元件从set每个位置data,给人的尺寸相同的一个布尔值阵列data.由于np.in1d在处理之前使输入变平,因此作为最后一步,我们需要将输出np.in1d重新2D整形为其原始形状.因此,最终的实施将是 -

np.in1d(data,np.hstack(test)).reshape(data.shape)
Run Code Online (Sandbox Code Playgroud)

样品运行 -

In [125]: data
Out[125]: 
array([[7, 0, 1, 8, 9, 5, 9, 1],
       [9, 7, 1, 4, 4, 2, 4, 4],
       [0, 4, 9, 6, 6, 3, 5, 9],
       [2, 2, 7, 7, 6, 7, 7, 2],
       [3, 4, 8, 4, 2, 1, 9, 8],
       [9, 0, 8, 1, 6, 1, 3, 5]])

In [126]: test
Out[126]: {3, 4, 6, 7, 9}

In [127]: np.in1d(data,np.hstack(test)).reshape(data.shape)
Out[127]: 
array([[ True, False, False, False,  True, False,  True, False],
       [ True,  True, False,  True,  True, False,  True,  True],
       [False,  True,  True,  True,  True,  True, False,  True],
       [False, False,  True,  True,  True,  True,  True, False],
       [ True,  True, False,  True, False, False,  True, False],
       [ True, False, False, False,  True, False,  True, False]], dtype=bool)
Run Code Online (Sandbox Code Playgroud)