Найти заданную разницу между двумя большими массивами (матрицами) в Python

У меня есть два больших массива 2-d, и я бы хотел найти их разницу в настройках, беря их ряды в качестве элементов. В Matlab код для этого будет setdiff(A,B,'rows'). Массивы достаточно велики, что явные методы цикла, о которых я мог думать, занимают слишком много времени.

Ответ 1

Эта должна работать, но в настоящее время нарушена в 1.6.1 из-за недоступной слияния для создаваемого представления. Он работает в версии до версии 1.7.0. Это должно быть самым быстрым способом, так как представлениям не нужно копировать любую память:

>>> import numpy as np
>>> a1 = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> a2 = np.array([[4,5,6],[7,8,9],[1,1,1]])
>>> a1_rows = a1.view([('', a1.dtype)] * a1.shape[1])
>>> a2_rows = a2.view([('', a2.dtype)] * a2.shape[1])
>>> np.setdiff1d(a1_rows, a2_rows).view(a1.dtype).reshape(-1, a1.shape[1])
array([[1, 2, 3]])

Вы можете сделать это в Python, но это может быть медленным:

>>> import numpy as np
>>> a1 = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> a2 = np.array([[4,5,6],[7,8,9],[1,1,1]])
>>> a1_rows = set(map(tuple, a1))
>>> a2_rows = set(map(tuple, a2))
>>> a1_rows.difference(a2_rows)
set([(1, 2, 3)])

Ответ 2

Вот хорошее альтернативное чистое решение numpy, которое работает для 1.6.1. Он создает промежуточный массив, поэтому это может быть или не быть проблемой для вас. Он также не полагается на какое-либо ускорение из отсортированного массива или нет (как это возможно setdiff).

from numpy import *
# Create some sample arrays
A =random.randint(0,5,(10,3))
B =random.randint(0,5,(10,3))

В качестве примера, это то, что я получил - обратите внимание, что существует один общий элемент:

>>> A
array([[1, 0, 3],
       [0, 4, 2],
       [0, 3, 4],
       [4, 4, 2],
       [2, 0, 2],
       [4, 0, 0],
       [3, 2, 2],
       [4, 2, 3],
       [0, 2, 1],
       [2, 0, 2]])
>>> B
array([[4, 1, 3],
       [4, 3, 0],
       [0, 3, 3],
       [3, 0, 3],
       [3, 4, 0],
       [3, 2, 3],
       [3, 1, 2],
       [4, 1, 2],
       [0, 4, 2],
       [0, 0, 3]])

Ищем, когда расстояние (L1) между строками равно нулю. Это дает нам матрицу, которая в точках, где она равна нулю, это элементы, общие для обоих списков:

idx = where(abs((A[:,newaxis,:] - B)).sum(axis=2)==0)

Как проверка:

>>> A[idx[0]]
array([[0, 4, 2]])
>>> B[idx[1]]
array([[0, 4, 2]])

Ответ 3

Я не уверен, для чего вы собираетесь, но это даст вам логический массив, в котором 2 массива не равны и будут быстрыми:


import numpy as np
a = np.random.randn(5, 5)
b = np.random.randn(5, 5)
a[0,0] = 10.0
b[0,0] = 10.0 
a[1,1] = 5.0
b[1,1] = 5.0
c = ~(a-b==0)
print c

[[False True True True True] [ True False True True True] [ True True True True True] [ True True True True True] [ True True True True True]]