Найдите строки, в которых a
содержит строки из b
:
duplicate_a = np.isin(a, b).all(axis=1)
Для этих строк найдите соответствующие строки в b:
duplicate_b = np.isin(b, a[duplicate_a, :]).all(axis=1)
, чтобы получить индексы эти дубликаты:
duplicate_b_rows = b[duplicate_b]
duplicate_b_indices = duplicate_b.nonzero()[0]
duplicate_a_indices = duplicate_a.nonzero()[0]
duplicates = [
(duplicate_a_indices[i], duplicate_b_indices[np.isin(duplicate_b_rows, row).all(axis=1)])
for i, row in enumerate(a[duplicate_a, :])
]
Например,
a = np.random.random((1000, 100))
b = np.random.random((500, 100))
b[1, :] = a[3, :]
b[5, :] = a[3, :]
b[2, :] = a[1, :]
Выводит
[(1, array([2])), (3, array([1, 5]))]
, указывая, что a [1,:] соответствует b [2,: ], а a [3,:] соответствует b [1,:], а также b [5,:].
Чтобы полностью сгладить это:
duplicates = [
(duplicate_a_indices[i], duplicate_b_indices[j])
for i, row in enumerate(a[duplicate_a, :]) for j in np.isin(duplicate_b_rows, row).all(axis=1).nonzero()[0]
]
Было бы теперь выведите [(1, 2), (3, 1), (3, 5)]
для приведенного выше примера
Но более быстрым способом было бы использовать таблицу поиска для строк:
a_lookup = {row.tostring(): i for i, row in enumerate(a)}
duplicates = [(a_lookup[row.tostring()], i) for i, row in enumerate(b) if row.tostring() in a_lookup]
Это работает намного быстрее, чем версия numpy в если у вас много строк, так как сложность равна O(N*K + M*K))
, где N
и M
- это количество строк в a и b соответственно, а K
- количество элементов в строке.
Хотя сложность решения numpy составляет O(M*N*K)
.
Обратите внимание, что это будет нормально работать для поиска точных дубликатов, но если ваши данные состоят из чисел с плавающей запятой, вы можете пропустить «дубликат» s ", которые по существу одинаковы, но из-за ограниченного разрешения поплавка будут отличаться на di git или более.