Сравнение массива numpy объекта dtype - PullRequest
0 голосов
/ 09 октября 2018

У меня вопрос "почему?":

aa[0]
array([[405, 162, 414, 0,
        array([list([1, 9, 2]), 18, (405, 18, 207), 64, 'Universal'],
      dtype=object),
        0, 0, 0]], dtype=object)

aaa
array([[405, 162, 414, 0,
        array([list([1, 9, 2]), 18, (405, 18, 207), 64, 'Universal'],
      dtype=object),
        0, 0, 0]], dtype=object)

np.array_equal(aaa,aa[0])
False

Эти массивы полностью идентичны.

Мой минимальный пример не воспроизводит это:

be=np.array([1],dtype=object)

be
array([1], dtype=object)

ce=np.array([1],dtype=object)

ce
array([1], dtype=object)

np.array_equal(be,ce)
True

И при этом это:

ce=np.array([np.array([1]),'5'],dtype=object)

be=np.array([np.array([1]),'5'],dtype=object)

np.array_equal(be,ce)
True

Однако, чтобы воспроизвести мою проблему, попробуйте это:

be=np.array([[405, 162, 414, 0, np.array([list([1, 9, 2]), 18, (405, 18, 207), 64, 'Universal'],dtype=object),0, 0, 0]], dtype=object)

ce=np.array([[405, 162, 414, 0, np.array([list([1, 9, 2]), 18, (405, 18, 207), 64, 'Universal'],dtype=object),0, 0, 0]], dtype=object)

np.array_equal(be,ce)
False

np.array_equal(be[0],ce[0])
False

И я понятия не имею, почему они не равны.И чтобы добавить бонусный вопрос, как мне их сравнить?

Мне нужен эффективный способ проверить, находится ли aaa в стеке aa.

Я не использую aaa in aa из-за DeprecationWarning: elementwise == comparison failed; this will raise an error in the future. и потому что он все еще возвращает False, если кому-то интересно.


Что еще я пробовал ?:

np.equal(be,ce)
*** ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

np.all(be,ce)
*** TypeError: only integer scalar arrays can be converted to a scalar index

all(be,ce)
*** TypeError: all() takes exactly one argument (2 given)

all(be==ce)
*** TypeError: 'bool' object is not iterable

np.where(be==ce)
(array([], dtype=int64),)

И эти, которые я не могу запустить в консоли, все оцениваются как False, некоторые дают предупреждение об устаревании:

import numpy as np

ce=np.array([[405, 162, 414, 0, np.array([list([1, 9, 2]), 18, (405, 18, 207), 64, 'Universal'],dtype=object),0, 0, 0]], dtype=object)

be=np.array([[405, 162, 414, 0, np.array([list([1, 9, 2]), 18, (405, 18, 207), 64, 'Universal'],dtype=object),0, 0, 0]], dtype=object)

print(np.any([bee in ce for bee in be]))

print(np.any([bee==cee for bee in be for cee in ce]))

print(np.all([bee in ce for bee in be]))

print(np.all([bee==cee for bee in be for cee in ce]))

И, конечно, другие вопросы говорит мне, что это должно работать ...

Ответы [ 3 ]

0 голосов
/ 09 октября 2018

В дополнение к ответу @ kmario23, что делать

def wrpr(bools):
    try:
      # ints  = bools.flatten().prod()
        fltn_bools = np.hstack(bools)
    except: # should not pass silently.
        fltn_bools = np.array(wrpr(a) for a in bools)        
    ints = fltn_bools.prod()
    if isinstance(ints, np.ndarray):
        return wrpr(ints)
    return bool(ints)

И, наконец,

>>> wrpr(np.equal(ce, be, dtype=np.object))
True

Проверено с использованием (numpy1.15.1 & Python 3.6.5) & (numpy1.15.1 & Python 2.7.13).


Но все же, как прокомментировано здесь

NumPy предназначен для жестких многомерных сетокчисел.Попытка получить что-либо кроме жесткой многомерной сетки будет болезненной. (@ user2357112, 31 июля '17 в 23:10)

и / или

Мораль истории: не использовать dtype=object массивов.Это задержанные списки Python с худшими характеристиками производительности, и numpy не предназначен для обработки контейнеров, подобных последовательности в этих массивах объектов. (@juanpa.arrivillaga, 31 июля '17 в 23:38)

0 голосов
/ 09 октября 2018

Поведение, которое вы видите, является задокументированным здесь

Устаревание¶

...

Сравнения равенства массивов объектов

В будущих сравнениях массивов объектов и ==, и np.equal больше не будут использовать проверки идентичности.Например:

>

a = np.array ([np.array ([1, 2, 3]), 1])

b = np.array ([np.array ([1, 2, 3]), 1])

a == b

будет последовательно возвращать False (и в будущем ошибку), даже если массив в a и b был одним и тем же объектом.

Оператор равенства == в будущем вызовет ошибки, такие как np.equal, если транслируетсяили сравнения элементов и т. д. не удаются.

Сравнение с arr == Никто в будущем не будет выполнять поэлементное сравнение вместо простого возврата False.Код должен использовать arr None.

Все эти изменения будут давать предупреждения об устаревании или FutureWarnings на данный момент.

Пока все ясно.Или это так?

Из ответа @ kmario23 видно, что начиная с версии 15.2 эти изменения еще не полностью реализованы.

Что еще хуже, учтите следующее:

>>> A = np.array([None, a])
>>> A1 = np.array([None, a])
>>> At = np.array([None, a[:2]])
>>> 
>>> A==A1
False
>>> A==At
array([ True, False])
>>> 

Похоже, что текущее поведение является скорее совпадением, чем результатом тщательного планирования.

Я подозреваю, что все сводится к тому, возникает ли исключение во время поэлементного сравнения, ср. здесь и здесь .

Если два соответствующих элемента содержащих их массивов являются самими массивами и имеют совместимые формы, как в A==A1, их сравнение дает массив bools,Попытка привести это к скалярному булу вызывает исключение.В настоящее время исключения регистрируются, и возвращается скалярное значение False.

В примере A==At возникает исключение при сравнении двух последних элементов, поскольку их формы не передаются.Это происходит, и сравнение для этого элемента возвращает скалярное значение False, поэтому сравнение содержащихся массивов возвращает «обычный» массив bools.

Как насчет обходных путей, предложенных @ kmario23 и @Kanak?Они работают?

Ну да ...

>>> np.equal(A, A1, dtype=object)
array([True, array([ True,  True,  True])], dtype=object)
>>> wrpr(np.equal(A, A1, dtype=object))
True

... и нет.

>>> AA = np.array([None, A])
>>> AA1 = np.array([None, A1])
>>> np.equal(AA, AA1, dtype=object)
array([True, False], dtype=object)
>>> wrpr(np.equal(AA, AA1, dtype=object))
False
0 голосов
/ 09 октября 2018

Для поэлементного сравнения массивов вы можете использовать numpy.equal() с аргументом ключевого слова dtype=numpy.object, например:

In [60]: np.equal(be, ce, dtype=np.object)
Out[60]: 
array([[True, True, True, True,
        array([ True,  True,  True,  True,  True]), True, True, True]],
      dtype=object)

PS проверено с использованием версии NumPy 1.15.2 и Python 3.6.6

edit

Из заметок о выпуске для 1.15,

https://docs.scipy.org/doc/numpy-1.15.1/release.html#comparison-ufuncs-accept-dtype-object-overriding-the-default-bool

Comparison ufuncs accept dtype=object, overriding the default bool

This allows object arrays of symbolic types, which override == and 
other operators to return expressions, to be compared elementwise with 
np.equal(a, b, dtype=object).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...