代码之家  ›  专栏  ›  技术社区  ›  Srivatsan

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

  •  4
  • Srivatsan  · 技术社区  · 6 年前

    我有两个数组 A (380万欧元)和 B (长度为20k)。 举个简单的例子,我们来看看这个例子:

    A = np.array([1,1,2,3,3,3,4,5,6,7,8,8])
    B = np.array([1,2,8])
    

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

    C = np.array([3,3,3,4,5,6,7])
    

    i、 e.如有任何价值 A A ,如果不是的话。

    我想知道有没有 for 因为它是一个很长的数组,所以循环需要很长时间。

    2 回复  |  直到 6 年前
        1
  •  12
  •   Divakar    4 年前

    使用 searchsorted

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

    A[B[np.searchsorted(B,A)] !=  A]
    

    searchsorted(a,v) 在排序数组中查找索引 a 这样,如果 v 如果在索引之前插入,则a的顺序将保持不变。那么,假设 idx = searchsorted(B,A) 我们索引到 与这些: B[idx] ,我们将得到 B类 对应于 A . 因此,将此映射版本与 A 会告诉我们 如果有匹配的话 B类 A

    一般情况( B类

    如果 B类

    或者,我们可以使用 sorter 与…争论 搜索排序 -

    sidx = B.argsort()
    out = A[B[sidx[np.searchsorted(B,A,sorter=sidx)]] != A]
    

    更一般的情况( A 值高于中的值

    sidx = B.argsort()
    idx = np.searchsorted(B,A,sorter=sidx)
    idx[idx==len(B)] = 0
    out = A[B[sidx[idx]] != A]
    

    使用 in1d/isin

    我们也可以使用 np.in1d B类 对于中的每个元素 A 然后我们可以使用带反转掩码的布尔索引来查找不匹配的索引-

    A[~np.in1d(A,B)]
    

    与相同 isin -

    A[~np.isin(A,B)]
    

    invert 旗帜-

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

    B类 不一定排序。

        2
  •  3
  •   SivolcC    6 年前

    我对numpy不是很熟悉,但是如何使用集合:

    C = set(A.flat) - set(B.flat)
    

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

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

    C = np.array(list(filter(lambda x: x not in B, A)))
    
        3
  •  1
  •   vmg    4 年前

    添加到 Divakar's answer 以上-

    如果原始数组A的范围比B大,则会出现“索引越界”错误。请参见:

    A = np.array([1,1,2,3,3,3,4,5,6,7,8,8,10,12,14])
    B = np.array([1,2,8])
    
    A[B[np.searchsorted(B,A)] !=  A]
    >> IndexError: index 3 is out of bounds for axis 0 with size 3
    
    

    np.searchsorted B[np.searchsorted(B,A)]

    为了避免这种情况,一种可能的方法是:

    def subset_sorted_array(A,B):
        Aa = A[np.where(A <= np.max(B))]
        Bb = (B[np.searchsorted(B,Aa)] !=  Aa)
        Bb = np.pad(Bb,(0,A.shape[0]-Aa.shape[0]), method='constant', constant_values=True)
        return A[Bb]
    

    # Take only the elements in A that would be inserted in B
    Aa = A[np.where(A <= np.max(B))]
    
    # Pad the resulting filter with 'Trues' - I split this in two operations for
    # easier reading
    Bb = (B[np.searchsorted(B,Aa)] !=  Aa)
    Bb = np.pad(Bb,(0,A.shape[0]-Aa.shape[0]),  method='constant', constant_values=True)
    
    # Then you can filter A by Bb
    A[Bb]
    # For the input arrays above:
    >> array([ 3,  3,  3,  4,  5,  6,  7, 10, 12, 14])
    

    请注意,这也适用于字符串数组和其他类型(对于需要比较的所有类型) <= 运算符已定义)。