如何在Python中实现matlab``aremember()``命令?

时间:2009-08-13 16:19:10

标签: python arrays matrix

这是我的问题:我想创建一个布尔矩阵B,其中包含True,矩阵A的值包含在向量v中。一个不方便的解决方案是:

import numpy as np
>>> A = np.array([[0,1,2], [1,2,3], [2,3,4]])
array([[0, 1, 2],
       [1, 2, 3],
       [2, 3, 4]])
>>> v = [1,2]
>>> B = (A==v[0]) + (A==v[1]) # matlab: ``B = ismember(A,v)``
array([[False,  True,  True],
       [ True,  True, False],
       [ True, False, False]], dtype=bool)

如果A和v有更多值,是否有更方便的解决方案?

干杯!

6 个答案:

答案 0 :(得分:4)

我不知道多少numpy,在这里是一个原始的蟒蛇:

>>> A = [[0,1,2], [1,2,3], [2,3,4]]
>>> v = [1,2]
>>> B = [map(lambda val: val in v, a) for a in A]
>>>
>>> B
[[False, True, True], [True, True, False], [True, False, False]]

编辑:正如Brooks Moses指出的那样,一些简单的时机似乎表明,这个可能会更好:

>>> B = [ [val in v for val in a] for a in A]

答案 1 :(得分:3)

使用numpy原语:

>>> import numpy as np
>>> A = np.array([[0,1,2], [1,2,3], [2,3,4]])
>>> v = [1,2]
>>> print np.vectorize(lambda x: x in v)(A)
[[False  True  True]
 [ True  True False]
 [ True False False]]

对于非微小输入,将v转换为先设置为大加速。

使用numpy.setmember1d:

Auniq, Ainv = np.unique1d(A, return_inverse=True)
result = np.take(np.setmember1d(Auniq, np.unique1d(v)), Ainv).reshape(A.shape)

答案 2 :(得分:3)

唉,当任何一个数组都有重复元素时,numpy中存在的setmember1d就会被破坏(如A所做)。下载this版本,在sys.path的某个地方调用它,例如sem.py,添加第一行import numpy as nm,然后这最终有效:

>>> import sem
>>> print sem.setmember1d(A.reshape(A.size), v).reshape(A.shape)
[[False True True]
 [True True False]
 [True False False]]

注意差异与@Aants'类似的答案:这个版本的结果bool数组的第二行是正确的,而他的版本(使用作为numpy的一部分的setmember1d)错误地将第二行作为所有True s。

答案 3 :(得分:2)

自Numpy 1.4版以来,有一个新函数in1d(),它相当于matlab中的ismember():http://docs.scipy.org/doc/numpy-1.6.0/reference/generated/numpy.in1d.html。但是,正如ars指出的那样,它只返回一个1d数组。

答案 4 :(得分:1)

这是一个天真的单行:

[any (value in item for value in v) for item in A]

示例输出:

>>> A = ( [0,1,2], [1,2,3], [2,3,4] )
>>> v = [1,2]
>>> [any (value in item for value in v) for item in A]
[True, True, True]
>>> v = [1]
>>> [any (value in item for value in v) for item in A]
[True, True, False]

这是一种非常Pythonic的方法,但我确信它不会在大型数组或向量上很好地扩展,因为Python的in运算符是线性搜索(至少在列表/元组上)。

正如Brooks Moses在下面的评论中指出的那样,输出应该是3x3矩阵。这就是你在问题中提供样本输出的原因。 (谢谢布鲁克斯)

>>> v=[1,2]
>>> [ [item in v for item in row] for row in A]
[[False, True, True], [True, True, False], [True, False, False]]
>>> v=[1]
>>> [ [item in v for item in row] for row in A]
[[False, True, False], [True, False, False], [False, False, False]]

答案 5 :(得分:1)

我认为你得到的最接近的是numpy.ismember1d,但它不适用于你的例子。我认为你的解决方案(B = (A==v[0]) + (A==v[1]))实际上可能是最好的解决方案。