Я ищу способ получить пересечение между двумя двумерными 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
, я был бы очень благодарен!
Как насчет использования наборов?
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)}
np.array(list(a.intersection(b)))
так как я хочу, чтобы вывод был numpy.array
. Спасибо за вашу помощь!
Индексированный пакет (выражение об отказе от ответственности: я его автор) был создан с точной целью предоставления такой функциональности выразительным и эффективным способом:
import numpy_indexed as npi
npi.intersect(a, b)
Обратите внимание, что реализация полностью векторизована; это не циклы над массивами в Python.
Другой подход заключается в использовании функции вещания
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]]
но это менее читабельно ИМО. [править]: или используйте уникальную и заданную комбинацию. Короче, вариантов много!
Вот способ обойтись без каких-либо циклов или списков, если у вас установлен 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]])
Создайте набор кортежей из первого массива и протестируйте каждую строку второго массива. Или наоборот.
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)
Одним из способов было бы использовать 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]])
Обратите внимание, что для двумерного случая этот подход не обобщается.