НумПи:Сравнение элементов в двух массивах

StackOverflow https://stackoverflow.com/questions/1613249

  •  06-07-2019
  •  | 
  •  

Вопрос

Кто-нибудь когда-нибудь сталкивался с этой проблемой?Допустим, у вас есть два массива, подобные следующему

a = array([1,2,3,4,5,6])
b = array([1,4,5])

Есть ли способ сравнить, какие элементы a существуют в b?Например,

c = a == b # Wishful example here
print c
array([1,4,5])
# Or even better
array([True, False, False, True, True, False])

Я пытаюсь избегать циклов, так как с миллионами элементов это займет много времени.Есть идеи?

Ваше здоровье

Это было полезно?

Решение

На самом деле, есть еще более простое решение, чем любое из этих:

import numpy as np

a = array([1,2,3,4,5,6])
b = array([1,4,5])

c = np.in1d(a,b)

В результате c будет:

array([ True, False, False,  True,  True, False], dtype=bool)

Другие советы

Используйте np.intersect1d.

#!/usr/bin/env python
import numpy as np
a = np.array([1,2,3,4,5,6])
b = np.array([1,4,5])
c=np.intersect1d(a,b)
print(c)
# [1 4 5]

Обратите внимание, что np.intersect1d дает неверный ответ, если a или b имеют неуникальные элементы.В этом случае используйте np.intersect1d_nu.

Также существуют np.setdiff1d, setxor1d, setmember1d и Union1d.ВидетьСписок примеров Numpy с документом

Спасибо за ответ kaizer.se.Это не совсем то, что я искал, но по совету друга и по вашим словам я пришел к следующему.

import numpy as np

a = np.array([1,4,5]).astype(np.float32)
b = np.arange(10).astype(np.float32)

# Assigning matching values from a in b as np.nan
b[b.searchsorted(a)] = np.nan

# Now generating Boolean arrays
match = np.isnan(b)
nonmatch = match == False

Это немного громоздкий процесс, но он лучше, чем написание циклов или использование переплетения с циклами.

Ваше здоровье

В Numpy есть функция установки numpy.setmember1d(), которая работает с отсортированными и уникальными массивами и возвращает именно тот логический массив, который вам нужен.Если входные массивы не соответствуют критериям, вам необходимо преобразовать их в установленный формат и инвертировать преобразование результата.

import numpy as np
a = np.array([6,1,2,3,4,5,6])
b = np.array([1,4,5])

# convert to the uniqued form
a_set, a_inv = np.unique1d(a, return_inverse=True)
b_set = np.unique1d(b)
# calculate matching elements
matches = np.setmea_set, b_set)
# invert the transformation
result = matches[a_inv]
print(result)
# [False  True False False  True  True False]

Редактировать:К сожалению, метод setmember1d в numpy действительно неэффективен.Предложенный вами метод сортировки и назначения поиска работает быстрее, но если вы можете назначать напрямую, вы можете также назначать непосредственно результату и избегать большого количества ненужного копирования.Также ваш метод потерпит неудачу, если b содержит что-то, чего нет в a.Следующие действия исправляют эти ошибки:

result = np.zeros(a.shape, dtype=np.bool)
idxs = a.searchsorted(b)
idxs = idxs[np.where(idxs < a.shape[0])] # Filter out out of range values
idxs = idxs[np.where(a[idxs] == b)] # Filter out where there isn't an actual match
result[idxs] = True
print(result)

Мои тесты показывают это при 91us vs.6,6 мс для вашего подхода и 109 мс для numpy setmember1d для 1M элемента a и 100 элемента b.

Эбрессет, Ваш ответ не будет работать, если a не является подмножеством b (и a и b не отсортированы).В противном случае searchsorted вернет ложные индексы.Мне пришлось сделать что-то подобное и объединить это с вашим кодом:

# Assume a and b are sorted
idxs = numpy.mod(b.searchsorted(a),len(b))
idxs = idxs[b[idxs]==a]
b[idxs] = numpy.nan
match = numpy.isnan(b)

Ваш пример подразумевает поведение, подобное установке, больше заботящееся о существование в массиве чем иметь правильный элемент в нужном месте.Numpy делает это по-другому со своими математическими массивами и матрицами: он расскажет вам только об элементах, находящихся в нужном месте.Можете ли вы заставить это работать на вас?

>>> import numpy
>>> a = numpy.array([1,2,3])
>>> b = numpy.array([1,3,3])
>>> a == b
array([ True, False,  True], dtype=bool)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top