2009-08-13 5 views
3

вот моя проблема:. Я хотел бы создать булеву матрицу B, которая содержит True всюду, что матрица А имеет значение, содержащееся в векторе V Один неудобное решение было бы:Как я могу реализовать команду `` ismember() `` `` mlabs в Python?

import numpy as np 
>>> A = np.array([[0,1,2], [1,2,3], [2,3,4]]) 
array([[0, 1, 2], 
     [1, 2, 3], 
     [2, 3, 4]]) 
>>> v = [1,2] 
>>> B = (A==v[0]) + (A==v[1]) # matlab: ``B = ismember(A,v)`` 
array([[False, True, True], 
     [ True, True, False], 
     [ True, False, False]], dtype=bool) 

Есть ли возможен решением, было бы более удобно, если бы А и v имели больше значений?

Cheers!

ответ

1

Вот наивная один вкладыш: выход

[any (value in item for value in v) for item in A] 

Пример:

>>> A = ([0,1,2], [1,2,3], [2,3,4]) 
>>> v = [1,2] 
>>> [any (value in item for value in v) for item in A] 
[True, True, True] 
>>> v = [1] 
>>> [any (value in item for value in v) for item in A] 
[True, True, False] 

Это очень Pythonic подход, но я уверен, что это не очень хорошо масштабируется на большие массивы или векторы потому что оператор in Python представляет собой линейный поиск (по крайней мере, по спискам/кортежам).

Как указал Брукс Мозес в нижеследующем комментарии, выход должен быть матрицей 3x3. Вот почему вы даете образец вывода в своих вопросах. (Спасибо Брукс)

>>> v=[1,2] 
>>> [ [item in v for item in row] for row in A] 
[[False, True, True], [True, True, False], [True, False, False]] 
>>> v=[1] 
>>> [ [item in v for item in row] for row in A] 
[[False, True, False], [True, False, False], [False, False, False]] 
+1

У вас есть хороший ответ на неправильный вопрос, я думаю, вы хотите, чтобы A был массивом 3x3 и возвращал значение истинности 3x3 для каждого из этих 9 элементов.Таким образом, слегка изменив ваш ответ: [[(элемент в v) для элемента в строке] для строки в A] отлично работает. Мне также интересно, почему вы ожидаете, что это будет медленным. –

4

Я не знаю много NumPy, здесь это сырье питона один:

>>> A = [[0,1,2], [1,2,3], [2,3,4]] 
>>> v = [1,2] 
>>> B = [map(lambda val: val in v, a) for a in A] 
>>> 
>>> B 
[[False, True, True], [True, True, False], [True, False, False]] 

Редактировать: Как Brooks Моисей отмечает и некоторые простые сроки, кажется, чтобы показать, это один, вероятно, будет лучше:

>>> B = [ [val in v for val in a] for a in A] 
+0

+1: Это работает с массивами numpy. –

+3

Наивный вопрос: почему синтаксис карты (лямбда ...), а не просто [(val in v) для v в a]? Есть ли существенная разница в этом случае? –

+0

@Brooks Moses: Вы правы, я думаю, что нет, и двойное понимание даже кажется немного быстрее (хотя я только сделал некоторые наивные сроки). Ред. – balpha

3

Использование Numpy примитивы:

>>> import numpy as np 
>>> A = np.array([[0,1,2], [1,2,3], [2,3,4]]) 
>>> v = [1,2] 
>>> print np.vectorize(lambda x: x in v)(A) 
[[False True True] 
[ True True False] 
[ True False False]] 

Для крошечных входов преобразуйте v в набор сначала для большого ускорения.

Чтобы использовать numpy.setmember1d:

Auniq, Ainv = np.unique1d(A, return_inverse=True) 
result = np.take(np.setmember1d(Auniq, np.unique1d(v)), Ainv).reshape(A.shape) 
+0

Это сломанно: см. 2-й ряд, самый правый столбец - что там Истинный? Это соответствует 3 в A, который НЕ находится в v. Увы, setmember1d НЕ поддерживает правильные массивы с дубликатами. –

+0

Исправлена ​​документация setmember1d. –

1

Я думаю, что ближайший вы получаете numpy.ismember1d, но это не будет хорошо работать с вашим примером. Я думаю, ваше решение (B = (A==v[0]) + (A==v[1])) действительно может быть лучшим.

3

Увы, setmember1d, поскольку он существует в numpy, ломается, когда любой массив имеет дублированные элементы (как это делает A). Скачать this версию, назовем его, например, sem.py где-нибудь на sys.path, добавить к нему первую линию import numpy as nm, а потом это, наконец, работает:

>>> import sem 
>>> print sem.setmember1d(A.reshape(A.size), v).reshape(A.shape) 
[[False True True] 
[True True False] 
[True False False]] 

Примечание аналогичный ответ Разница WRT @Aants': эту версию имеет вторую строку полученного массива bool правильно, в то время как его версия (с использованием setmember1d, которая поставляется как часть numpy) неправильно имеет вторую строку, как и все True s.

Смежные вопросы