我有一个 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/