如果存在于另一个数组中,则从一个数组中删除元素,保留重复项 - NumPy/Python

The*_*tor 5 python for-loop numpy unique

我有两个数组A(len为380万)和B(len为20k).对于最小的例子,让我们来看看这个案例:

A = np.array([1,1,2,3,3,3,4,5,6,7,8,8])
B = np.array([1,2,8])
Run Code Online (Sandbox Code Playgroud)

现在我希望得到的数组是:

C = np.array([3,3,3,4,5,6,7])
Run Code Online (Sandbox Code Playgroud)

即如果B找到任何值,则A删除它A,如果不保留它.

我想知道是否有任何方法可以在没有for循环的情况下进行,因为它是一个冗长的数组,因此循环需要很长时间.

Div*_*kar 8

运用 searchsorted

有了排序B,我们可以使用searchsorted-

A[B[np.searchsorted(B,A)] !=  A]
Run Code Online (Sandbox Code Playgroud)

从链接的文档中,searchsorted(a,v)将索引查找为已排序的数组,以便在索引之前插入a相应的元素时v,将保留a的顺序.所以,让我们说idx = searchsorted(B,A),我们B用那些索引:B[idx]我们将得到一个B对应于每个元素的映射版本A.因此,比较这个映射版本A会告诉我们每个元素A是否存在匹配B.最后,索引到A选择不匹配的.

通用案例(B未排序):

如果B尚未按先决条件排序,则对其进行排序,然后使用建议的方法.

或者,我们可以使用sorter参数searchsorted-

sidx = B.argsort()
out = A[B[sidx[np.searchsorted(B,A,sorter=sidx)]] != A]
Run Code Online (Sandbox Code Playgroud)

运用 in1d/isin

我们也可以使用np.in1d,这是非常简单的(链接的文档应该有助于澄清),因为它寻找B每个元素的任何匹配 A,然后我们可以使用带有反转掩码的布尔索引来查找不匹配的 -

A[~np.in1d(A,B)]
Run Code Online (Sandbox Code Playgroud)

isin- 相同

A[~np.isin(A,B)]
Run Code Online (Sandbox Code Playgroud)

invert旗帜 -

A[np.in1d(A,B,invert=True)]

A[np.isin(A,B,invert=True)]
Run Code Online (Sandbox Code Playgroud)

这解决了一般情况B下不必排序.


Clo*_*loC 5

我对 numpy 不太熟悉,但是使用集合怎么样:

C = set(A.flat) - set(B.flat)
Run Code Online (Sandbox Code Playgroud)

编辑:从注释中,集合不能有重复值。

所以另一个解决方案是使用 lambda 表达式:

C = np.array(list(filter(lambda x: x not in B, A)))
Run Code Online (Sandbox Code Playgroud)