import numpy
data = numpy.random.randint(0, 10, (6,8))
test = set(numpy.random.randint(0, 10, 5))
我想要一个表达式,其值是一个 bool 数组,具有与 data
相同的形状(或者,至少,可以 reshape 为相同的形状),它告诉我是否相应的项在data
在 set
中。
例如,如果我想知道 data
的哪些元素严格小于 6
,我可以使用一个向量化表达式,
a = data < 6
计算 6x8
bool 值 ndarray。相反,当我尝试一个表面上等价的 bool 表达式时
b = data in test
我得到的是一个异常(exception):
TypeError: unhashable type: 'numpy.ndarray'
附录——对不同的解决方案进行基准测试
编辑:下面的可能性 #4 给出了错误的结果,感谢 hpaulj 和 Divakar 让我走上了正确的道路。
这里我比较了四种不同的可能性,
- Divakar 提出的
np.in1d(data, np.hstack(test))
。 - hpaulj 的一项提案,
np.in1d(data, np.array(list(test)))
。 - hpaulj 的另一个提议,`np.in1d(data, np.fromiter(test, int))。
作者删除了答案中提出的内容,我不记得作者的名字,np.in1d(data, test)
。
这是 Ipython session ,略微编辑以避免空行
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
在 [9]: %timeit np.in1d(data, test)
1000 次循环,3 次循环中的最佳次数:每次循环 687 微秒
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
在 [17]: %timeit np.in1d(data, test)
10 个循环,3 个循环中的最佳:每个循环 67.9 毫秒
In [18]:
(现在)匿名发布者的回答给出了更好的时间。
事实证明,匿名发布者有充分的理由删除他们的答案,结果是错误的!
正如 hpaulj 评论的那样,在 in1d
的文档中有一条警告不要将 set
用作第二个参数,但我更想要一个明确的如果计算结果可能是错误的,则失败。
也就是说,使用 numpy.fromiter()
的解决方案具有最好的数字...
最佳答案
我假设您正在寻找一个 bool 数组来检测 data
数组中是否存在 set
元素。为此,您可以使用 np.hstack
从 set
中提取元素。然后使用 np.in1d
检测 data
中 each 位置是否存在 set
中的any 元素,为我们提供相同的 bool 数组大小为 data
。由于 np.in1d
在处理之前将输入变平,因此作为最后一步,我们需要将 np.in1d
的输出 reshape 回其原始 2D
形状。因此,最终的实现将是 -
np.in1d(data,np.hstack(test)).reshape(data.shape)
sample 运行-
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)
关于python - 集合中的数组元素是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37774990/