python - 如果它出现在纯 numpy 中的另一个数组中,则有效地删除数组的每一行

标签 python arrays numpy

我有一个 numpy 数组,其中索引以 (n, 2) 的形式存储。例如:

[[0, 1],
 [2, 3], 
 [1, 2], 
 [4, 2]]

然后我进行一些处理并创建一个形状为 (m, 2) 的数组,其中 n > m。例如:

[[2, 3]
 [4, 2]]

现在我想删除第一个数组中也可以在第二个数组中找到的每一行。所以我想要的结果是:

[[0, 1], 
 [1, 2]]

我目前的解决方案如下:

for row in second_array:
        result = np.delete(first_array, np.where(np.all(first_array == second_array, axis=1)), axis=0)

但是,如果秒数很大,这会非常耗时。有人知道不需要循环的仅 numpy 解决方案吗?

最佳答案

这是一个利用它们是正数的事实,使用 matrix-multiplication 进行降维 -

def setdiff_nd_positivenums(a,b):
    s = np.maximum(a.max(0)+1,b.max(0)+1)
    return a[~np.isin(a.dot(s),b.dot(s))]

sample 运行-

In [82]: a
Out[82]: 
array([[0, 1],
       [2, 3],
       [1, 2],
       [4, 2]])

In [83]: b
Out[83]: 
array([[2, 3],
       [4, 2]])

In [85]: setdiff_nd_positivenums(a,b)
Out[85]: 
array([[0, 1],
       [1, 2]])

此外,第二个数组 b 似乎是 a 的子集。因此,我们可以利用该场景使用 np.searchsorted 进一步提升性能,就像这样 -

def setdiff_nd_positivenums_searchsorted(a,b):
    s = np.maximum(a.max(0)+1,b.max(0)+1)
    a1D,b1D = a.dot(s),b.dot(s)
    b1Ds = np.sort(b1D)
    return a[b1Ds[np.searchsorted(b1Ds,a1D)] != a1D]

时间 -

In [146]: np.random.seed(0)
     ...: a = np.random.randint(0,9,(1000000,2))
     ...: b = a[np.random.choice(len(a), 10000, replace=0)]

In [147]: %timeit setdiff_nd_positivenums(a,b)
     ...: %timeit setdiff_nd_positivenums_searchsorted(a,b)
10 loops, best of 3: 101 ms per loop
10 loops, best of 3: 70.9 ms per loop

对于通用数字,这是另一个使用 views -

# https://stackoverflow.com/a/45313353/ @Divakar
def view1D(a, b): # a, b are arrays
    a = np.ascontiguousarray(a)
    b = np.ascontiguousarray(b)
    void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
    return a.view(void_dt).ravel(),  b.view(void_dt).ravel()

def setdiff_nd(a,b):
    # a,b are the nD input arrays
    A,B = view1D(a,b)    
    return a[~np.isin(A,B)]

sample 运行-

In [94]: a
Out[94]: 
array([[ 0,  1],
       [-2, -3],
       [ 1,  2],
       [-4, -2]])

In [95]: b
Out[95]: 
array([[-2, -3],
       [ 4,  2]])

In [96]: setdiff_nd(a,b)
Out[96]: 
array([[ 0,  1],
       [ 1,  2],
       [-4, -2]])

时间 -

In [158]: np.random.seed(0)
     ...: a = np.random.randint(0,9,(1000000,2))
     ...: b = a[np.random.choice(len(a), 10000, replace=0)]

In [159]: %timeit setdiff_nd(a,b)
1 loop, best of 3: 352 ms per loop

关于python - 如果它出现在纯 numpy 中的另一个数组中,则有效地删除数组的每一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55530975/

相关文章:

php - 是否可以在没有循环的情况下更改数组的所有值?

python - 基于元素的 n 个连续实例对 pandas df 进行切片

python - 距离矩阵的坐标列表

python - 欧拉问题 #4

python - 如何使用递归方式将二进制转换为十进制?

arrays - 在 O(n) 时间内找到数组中的 10 个最大整数

java - 二维 boolean 数组垂直、水平和对角线赋值

python - Matlab 和 numpy/scipy 中的 FFT 给出不同的结果

python - 错误 "' 类型'对象没有属性 '__getitem__'“当遍历列表 ["a","b","c"]

python - 如何使用 Django 创建用户到用户的消息系统?