从一个数组中删除另一个数组中的元素

新手上路,请多包涵

假设我有这些二维数组 AB

如何从 A 中删除 B 中的元素。 (集合论补:AB)

 A=np.asarray([[1,1,1], [1,1,2], [1,1,3], [1,1,4]])
B=np.asarray([[0,0,0], [1,0,2], [1,0,3], [1,0,4], [1,1,0], [1,1,1], [1,1,4]])
#output = [[1,1,2], [1,1,3]]


更准确地说,我想做这样的事情。

 data = some numpy array
label = some numpy array
A = np.argwhere(label==0) #[[1 1 1], [1 1 2], [1 1 3], [1 1 4]]
B = np.argwhere(data>1.5) #[[0 0 0], [1 0 2], [1 0 3], [1 0 4], [1 1 0], [1 1 1], [1 1 4]]
out = np.argwhere(label==0 and data>1.5) #[[1 1 2], [1 1 3]]

原文由 Jee Seok Yoon 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

基于 this solutionFind the row indexes of several values in a numpy array ,这是一个基于 NumPy 的解决方案,内存占用更少,在处理大型数组时可能会有所帮助 -

 dims = np.maximum(B.max(0),A.max(0))+1
out = A[~np.in1d(np.ravel_multi_index(A.T,dims),np.ravel_multi_index(B.T,dims))]

样品运行 -

 In [38]: A
Out[38]:
array([[1, 1, 1],
       [1, 1, 2],
       [1, 1, 3],
       [1, 1, 4]])

In [39]: B
Out[39]:
array([[0, 0, 0],
       [1, 0, 2],
       [1, 0, 3],
       [1, 0, 4],
       [1, 1, 0],
       [1, 1, 1],
       [1, 1, 4]])

In [40]: out
Out[40]:
array([[1, 1, 2],
       [1, 1, 3]])

大型阵列的运行时测试 -

 In [107]: def in1d_approach(A,B):
     ...:     dims = np.maximum(B.max(0),A.max(0))+1
     ...:     return A[~np.in1d(np.ravel_multi_index(A.T,dims),\
     ...:                     np.ravel_multi_index(B.T,dims))]
     ...:

In [108]: # Setup arrays with B as large array and A contains some of B's rows
     ...: B = np.random.randint(0,9,(1000,3))
     ...: A = np.random.randint(0,9,(100,3))
     ...: A_idx = np.random.choice(np.arange(A.shape[0]),size=10,replace=0)
     ...: B_idx = np.random.choice(np.arange(B.shape[0]),size=10,replace=0)
     ...: A[A_idx] = B[B_idx]
     ...:

基于 broadcasting 解决方案的计时 -

 In [109]: %timeit A[np.all(np.any((A-B[:, None]), axis=2), axis=0)]
100 loops, best of 3: 4.64 ms per loop # @Kasramvd's soln

In [110]: %timeit A[~((A[:,None,:] == B).all(-1)).any(1)]
100 loops, best of 3: 3.66 ms per loop

基于较少内存占用的解决方案的计时 -

 In [111]: %timeit in1d_approach(A,B)
1000 loops, best of 3: 231 µs per loop

进一步提升性能

in1d_approach 通过将每一行视为索引元组来减少每一行。我们可以通过使用 np.dot 引入矩阵乘法来更有效地做同样的事情,就像这样 -

 def in1d_dot_approach(A,B):
    cumdims = (np.maximum(A.max(),B.max())+1)**np.arange(B.shape[1])
    return A[~np.in1d(A.dot(cumdims),B.dot(cumdims))]

让我们在更大的阵列上与之前的相比进行测试 -

 In [251]: # Setup arrays with B as large array and A contains some of B's rows
     ...: B = np.random.randint(0,9,(10000,3))
     ...: A = np.random.randint(0,9,(1000,3))
     ...: A_idx = np.random.choice(np.arange(A.shape[0]),size=10,replace=0)
     ...: B_idx = np.random.choice(np.arange(B.shape[0]),size=10,replace=0)
     ...: A[A_idx] = B[B_idx]
     ...:

In [252]: %timeit in1d_approach(A,B)
1000 loops, best of 3: 1.28 ms per loop

In [253]: %timeit in1d_dot_approach(A, B)
1000 loops, best of 3: 1.2 ms per loop

原文由 Divakar 发布,翻译遵循 CC BY-SA 3.0 许可协议

有一个 列表理解 的简单解决方案,

 A = [i for i in A if i not in B]

结果

[[1, 1, 2], [1, 1, 3]]

列表理解不是从数组中删除元素,它只是重新分配 - 如果要删除元素,请使用此方法:

 for i in B:
     if i in A:
     A.remove(i)

原文由 Rahul K P 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题