ValueError: значение истинности массива с более чем одним элементом неоднозначно. Использовать.любой() или.все()



Я только что обнаружил логическую ошибку в моем коде, который вызывает всевозможные проблемы. Я непреднамеренно делал побитовое и вместо логические и.



Я изменил код:



r = mlab.csv2rec(datafile, delimiter=',', names=COL_HEADERS)
mask = ((r["dt"] >= startdate) & (r["dt"] <= enddate))
selected = r[mask]


TO:



r = mlab.csv2rec(datafile, delimiter=',', names=COL_HEADERS)
mask = ((r["dt"] >= startdate) and (r["dt"] <= enddate))
selected = r[mask]


к моему удивлению, я получил весьма загадочное сообщение об ошибке:




ValueError: значение истинности массива с более чем одним элементом равно
неоднозначный. Используйте a. any () или а.все()




почему подобная ошибка не была выдана, когда я использую побитовую операцию - и как это исправить?

1603   3  

3 ответов:

r - это массив numpy (rec). Так что r["dt"] >= startdate также (логическое) матрица. Для массивов numpy в & операция возвращает поразрядное и двух логические массивы.

разработчики NumPy чувствовали, что не было ни одного общепринятого способа оценки массив в логическом контексте: это может означать True если любой элемент True, или это может означать True если все элементы True или True если массив имеет ненулевую длину, просто назовите три возможности.

поскольку у разных пользователей могут быть разные потребности и разные предположения, Разработчики NumPy отказались гадать и вместо этого решили поднять ValueError всякий раз, когда кто-то пытается оценить массив в логическом контексте. Применение and to два массива numpy приводит к тому, что два массива вычисляются в логическом контексте (по звоню __bool__ в Python3 или __nonzero__ в Python2).

ваш исходный код

mask = ((r["dt"] >= startdate) & (r["dt"] <= enddate))
selected = r[mask]

выглядит правильно. Однако, если вы хотите and, вместо a and b использовать (a-b).any() или (a-b).all().

у меня была такая же проблема (т. е. индексирование с несколькими условиями, здесь это поиск данных в определенном диапазоне дат). Элемент (a-b).any() или (a-b).all() Кажется, не работает, по крайней мере для меня.

в качестве альтернативы я нашел другое решение, которое отлично работает для моей желаемой функциональности (https://stackoverflow.com/questions/12647471/the-truth-value-of-an-array-with-more-than-one-element-is-ambigous-when-trying-t).

вместо использования предложенного выше кода, просто используя numpy.logical_and(a,b) будет работать. Здесь вы можете переписать код как

selected = r(logical_and(r["dt"] >= startdate, r["dt"] <= enddate))

причина исключения в том, что and неявно называет bool. Сначала на левом операнде и (если левый операнд True), затем на правый операнд. Так что x and y эквивалентно bool(x) and bool(y).

на bool на numpy.ndarray (если он содержит более одного элемента) вызовет исключение, которое вы видели:
>>> import numpy as np
>>> arr = np.array([1, 2, 3])
>>> bool(arr)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

The bool() вызов подразумевается в and, но и if,while,or, так что любой из следующих примеры также потерпят неудачу:

>>> arr and arr
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

>>> if arr: pass
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

>>> while arr: pass
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

>>> arr or arr
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

в Python есть больше функций и операторов, которые скрывают bool звонит, например 2 < x < 10 - это просто другой способ написания 2 < x and x < 10. А то and будем называть bool:bool(2 < x) and bool(x < 10).

The элемент-мудрый эквивалентно and будет np.logical_and функция, аналогично вы могли бы использовать np.logical_or как эквивалент or.

для логических массивов-и сравнения типа <,<=,==,!=,>= и > на массивы NumPy возвращают логические массивы NumPy-вы также можете использовать элемент-мудрый побитового функции (и операторов): np.bitwise_and (& оператор)

>>> np.logical_and(arr > 1, arr < 3)
array([False,  True, False], dtype=bool)

>>> np.bitwise_and(arr > 1, arr < 3)
array([False,  True, False], dtype=bool)

>>> (arr > 1) & (arr < 3)
array([False,  True, False], dtype=bool)

и bitwise_or (| оператор):

>>> np.logical_or(arr <= 1, arr >= 3)
array([ True, False,  True], dtype=bool)

>>> np.bitwise_or(arr <= 1, arr >= 3)
array([ True, False,  True], dtype=bool)

>>> (arr <= 1) | (arr >= 3)
array([ True, False,  True], dtype=bool)

полный список логических и двоичных функций можно найти в NumPy документация:

Comments

    Ничего не найдено.