Проверьте, не содержат ли два трехмерных массива перекрывающиеся двухмерные массивы.

1

У меня есть два очень больших массива 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 - двумерные массивы) Мне нужно найти количество перекрывающихся массивов, но не конкретные.

  • 0
    Не уверен, что это то, что вы хотели, но вы можете проверить пересечение для каждого затемнения, а затем пересечь результат
  • 0
    Нет. В моем сценарии есть объект во втором и третьем измерениях. Я хочу проверить, появляются ли эти объекты в другом массиве, и если да, то сколько.
Показать ещё 5 комментариев
Теги:
arrays
numpy
multidimensional-array

1 ответ

4
Лучший ответ

Мы могли бы использовать 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

Итак, эти два решения дают нам маску присутствия каждого из подмассивов из 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
  • 0
    Это работает, большое спасибо! Вы понятия не имеете, сколько времени я застрял на этом LOL

Ещё вопросы

Сообщество Overcoder
Наверх
Меню