Пересечение двумерных массивов

1

Я ищу способ получить пересечение между двумя двумерными numpy.array shape (n_1, m) и (n_2, m). Обратите внимание, что n_1 и n_2 могут различаться, но m одинаково для обоих массивов. Вот два минимальных примера с ожидаемыми результатами:

import numpy as np

array1a = np.array([[2], [2], [5], [1]])
array1b = np.array([[5], [2]])

array_intersect(array1a, array1b)
##  array([[2],
##         [5]])


array2a = np.array([[1, 2], [3, 3], [2, 1], [1, 3], [2, 1]])
array2b = np.array([[2, 1], [1, 4], [3, 3]])

array_intersect(array2a, array2b)
##  array([[2, 1],
##         [3, 3]])

Если кто-то знает, как мне реализовать функцию array_intersect, я был бы очень благодарен!

  • 0
    Извините, я не могу понять, как именно вы определяете пересечение. Это матрица, состоящая из всех строк второй матрицы, представленной в первой? Или наоборот?
  • 0
    Извините, если мне было непонятно! Я просто хочу, чтобы любая строка, которая существует в двух массивах, была возвращена.
Теги:
numpy

6 ответов

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

Как насчет использования наборов?

import numpy as np

array2a = np.array([[1, 2], [3, 3], [2, 1], [1, 3], [2, 1]])
array2b = np.array([[2, 1], [1, 4], [3, 3]])


a = set((tuple(i) for i in array2a))
b = set((tuple(i) for i in array2b))

a.intersection(b) # {(2, 1), (3, 3)}
  • 0
    Это мой любимый, так как его легче читать. Я реализовал это в функции, где я возвращаю np.array(list(a.intersection(b))) так как я хочу, чтобы вывод был numpy.array . Спасибо за вашу помощь!
  • 0
    Это может быть приемлемо с точки зрения производительности для небольших массивов; но обратите внимание, что это исключает похожую на производительность производительность и включает в себя создание множества отдельных объектов Python с соответствующими накладными расходами.
0

Индексированный пакет (выражение об отказе от ответственности: я его автор) был создан с точной целью предоставления такой функциональности выразительным и эффективным способом:

import numpy_indexed as npi
npi.intersect(a, b)

Обратите внимание, что реализация полностью векторизована; это не циклы над массивами в Python.

0

Другой подход заключается в использовании функции вещания

import numpy as np

array2a = np.array([[1, 2], [3, 3], [2, 1], [1, 3], [2, 1]])
array2b = np.array([[2, 1], [1, 4], [3, 3]])

test = array2a[:, None] == array2b
print(array2b[np.all(test.mean(0) > 0, axis = 1)]) # [[2 1]
                                                   # [3 3]]

но это менее читабельно ИМО. [править]: или используйте уникальную и заданную комбинацию. Короче, вариантов много!

0

Вот способ обойтись без каких-либо циклов или списков, если у вас установлен scipy (я не проверял скорость):

In [31]: from scipy.spatial.distance import cdist

In [32]: np.unique(array1a[np.where(cdist(array1a, array1b) == 0)[0]], axis=0)
Out[32]: 
array([[2],
       [5]])

In [33]: np.unique(array2a[np.where(cdist(array2a, array2b) == 0)[0]], axis=0)
Out[33]: 
array([[2, 1],
       [3, 3]])
0

Создайте набор кортежей из первого массива и протестируйте каждую строку второго массива. Или наоборот.

def array_intersect(a, b):
    s = {tuple(x) for x in a}
    return np.unique([x for x in b if tuple(x) in s], axis=0)
-1

Одним из способов было бы использовать numpy.intersect1d как в:

In [33]: res = np.intersect1d(array1b, array1a, return_indices=True)
In [34]: res_arr, idxs = res[0], res[1:]

In [38]: res_arr.reshape(res_arr.shape[0], -1)
Out[38]: 
array([[2],
       [5]])

Обратите внимание, что для двумерного случая этот подход не обобщается.

Ещё вопросы

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