假设我有numpy数组
a = np.array([1,3,5,7,9,11,13])
b = np.array([3,5,7,11,13])
我想创建一个a大小的布尔数组,其中每个条目为True或False取决于a的元素是否也在b中。
所以在这种情况下,我要
a_b = np.array([False,True,True,True,False,True,True]).
当b由一个元素组成== b [0]时,我可以执行此操作。当b的长度大于1时,有没有一种快速的方法?
python大神给出的解决方案
使用numpy.in1d
:
In [672]: np.in1d([1,2,3,4], [1,2])
Out[672]: array([ True, True, False, False], dtype=bool)
为您的数据:
In [674]: np.in1d(a, b)
Out[674]: array([False, True, True, True, False, True, True], dtype=bool)
根据文档,此版本在1.4.0或更高版本中可用。该文档还描述了该操作在纯Python中的外观:
对于一维序列,in1d
可被视为python关键字in
的逐元素函数版本。 in1d(a, b)
大致等同于np.array([item in b for item in a])
。
该函数的文档值得一读,因为其中有invert
关键字参数和assume_unique
关键字参数-在某些情况下,每种参数都非常有用。
我还发现使用np.vectorize
和operator.contains
创建自己的版本很有趣:
from operator import contains
v_in = np.vectorize(lambda x,y: contains(y, x), excluded={1,})
然后:
In [696]: v_in([1,2,3, 2], [1, 2])
Out[696]: array([ True, True, False, True], dtype=bool)
因为operator.contains
会翻转参数,所以我需要lambda
来使调用约定与您的用例匹配-但如果可以先使用b
然后使用a
调用,则可以跳过此步骤。
但是请注意,您需要对excluded
使用vectorize
选项,因为您希望代表b
序列的任何参数(用于检查其成员资格的序列)实际上都保留为序列(因此,如果您选择不翻转)将contains
参数与lambda
一起使用,则需要排除索引0
而不是1
)。
使用in1d
的方法肯定会更快,并且会更好,因为它依赖于众所周知的内置函数。但是,有时候知道如何使用operator
和vectorize
来完成这些技巧是很好的。
您甚至可以为此创建一个Python Infix recipe instance,然后将v_in
用作“中缀”操作:
v_in = Infix(np.vectorize(lambda x,y: contains(y, x), excluded={1,}))
# even easier: v_in = Infix(np.in1d)
和示例用法:
In [702]: v_in([1, 2, 3, 2], [1, 2])
Out[702]: array([ True, True, False, True], dtype=bool)
In [704]: [1, 2, 3, 2] <<v_in>> [1, 2]
Out[704]: array([ True, True, False, True], dtype=bool)