我有两个非常大的numpy数组,它们都是3D的。我需要找到一种有效的方法来检查它们是否重叠,因为首先将它们都转换为集合会花费很长时间。我尝试使用在此找到的另一个解决方案来解决相同的问题,但适用于2D阵列,但是我没有设法使其适用于3D。这是2D解决方案:
nrows, ncols = A.shape dtype={'names':['f{}'.format(i) for i in range(ndep)], 'formats':ndep * [A.dtype]} C = np.intersect1d(A.view(dtype).view(dtype), B.view(dtype).view(dtype)) # This last bit is optional if you're okay with "C" being a structured array... C = C.view(A.dtype).reshape(-1, ndep)
(其中A和B是2D数组)我需要找到重叠的numpy数组的数量,而不是特定的数组。
我们可以利用views我在一些问答中使用过的辅助功能来发挥作用。要获得子数组的存在,我们可以np.isin在视图上使用或使用更加费力的视图np.searchsorted。
views
np.isin
np.searchsorted
方法1: 使用np.isin-
# 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 isin_nd(a,b): # a,b are the 3D input arrays to give us "isin-like" functionality across them A,B = view1D(a.reshape(a.shape[0],-1),b.reshape(b.shape[0],-1)) return np.isin(A,B)
方法2: 我们也可以利用np.searchsorted于views-
def isin_nd_searchsorted(a,b): # a,b are the 3D input arrays A,B = view1D(a.reshape(a.shape[0],-1),b.reshape(b.shape[0],-1)) sidx = A.argsort() sorted_index = np.searchsorted(A,B,sorter=sidx) sorted_index[sorted_index==len(A)] = len(A)-1 idx = sidx[sorted_index] return A[idx] == B
因此,这两个解决方案为我们提供了ain中每个子数组的存在掩码b。因此,为了获得所需的计数,它应该是-isin_nd(a,b).sum()或isin_nd_searchsorted(a,b).sum()。
a
b
isin_nd(a,b).sum()
isin_nd_searchsorted(a,b).sum()
样品运行-
In [71]: # Setup with 3 common "subarrays" ...: np.random.seed(0) ...: a = np.random.randint(0,9,(10,4,5)) ...: b = np.random.randint(0,9,(7,4,5)) ...: ...: b[1] = a[4] ...: b[3] = a[2] ...: b[6] = a[0] In [72]: isin_nd(a,b).sum() Out[72]: 3 In [73]: isin_nd_searchsorted(a,b).sum() Out[73]: 3
大型阵列上的时间-
In [74]: # Setup ...: np.random.seed(0) ...: a = np.random.randint(0,9,(100,100,100)) ...: b = np.random.randint(0,9,(100,100,100)) ...: idxa = np.random.choice(range(len(a)), len(a)//2, replace=False) ...: idxb = np.random.choice(range(len(b)), len(b)//2, replace=False) ...: a[idxa] = b[idxb] # Verify output In [82]: np.allclose(isin_nd(a,b),isin_nd_searchsorted(a,b)) Out[82]: True In [75]: %timeit isin_nd(a,b).sum() 10 loops, best of 3: 31.2 ms per loop In [76]: %timeit isin_nd_searchsorted(a,b).sum() 100 loops, best of 3: 1.98 ms per loop