Удалить элементы из одного массива, если они присутствуют в другом массиве, сохранить дубликаты - NumPy / Python - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть два массива A (длина 3,8 миллиона) и B (длина 20 тысяч).Для минимального примера, давайте возьмем этот случай:

A = np.array([1,1,2,3,3,3,4,5,6,7,8,8])
B = np.array([1,2,8])

Теперь я хочу, чтобы результирующий массив был:

C = np.array([3,3,3,4,5,6,7])

, т. Е. Если найдено какое-либо значение в Bв A удалите его из A, если не сохраните.

Я хотел бы знать, есть ли какой-либо способ сделать это без for loop потому что это длинный массив и поэтому для его создания требуется много времени.

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

Я не очень знаком с NumPy, но как насчет использования наборов:

C = set(A.flat) - set(B.flat)

РЕДАКТИРОВАТЬ: из комментариев, наборы не могут иметь дублирующиеся значения.

Таким образом, другое решение будет использоватьлямбда-выражение:

C = np.array(list(filter(lambda x: x not in B, A)))
0 голосов
/ 20 сентября 2018

Используя searchsorted

С отсортированным B, мы можем использовать searchsorted -

A[B[np.searchsorted(B,A)] !=  A]

Из связанных документов searchsorted(a,v) найтииндексы в отсортированный массив a, так что, если соответствующие элементы в v были вставлены перед индексами, порядок a будет сохранен.Итак, скажем idx = searchsorted(B,A) и мы индексируем в B с такими: B[idx], мы получим отображенную версию B, соответствующую каждому элементу в A.Таким образом, сравнение этой отображенной версии с A скажет нам для каждого элемента в A, есть ли совпадение в B или нет.Наконец, индекс в A для выбора несовпадающих.

Общий регистр (B не отсортирован):

Если B неуже отсортировано как предварительное условие, отсортируйте его и затем используйте предложенный метод.

В качестве альтернативы, мы можем использовать sorter аргумент с searchsorted -

sidx = B.argsort()
out = A[B[sidx[np.searchsorted(B,A,sorter=sidx)]] != A]

Использование in1d/isin

Мы также можем использовать np.in1d, что довольно просто (связанные документы должны помочь прояснить), поскольку он ищет любое совпадение в B для каждогоэлемент в A, а затем мы можем использовать логическое индексирование с инвертированной маской для поиска несоответствующих -

A[~np.in1d(A,B)]

То же самое с isin -

A[~np.isin(A,B)]

Сinvert flag -

A[np.in1d(A,B,invert=True)]

A[np.isin(A,B,invert=True)]

Это решает для универсального, когда B не обязательно сортируется.

...