Ik heb zojuist een logische bug in mijn code ontdekt die allerlei problemen veroorzaakte. Ik deed per ongeluk een bitsgewijze EN in plaats van een logische EN.
Ik heb de code gewijzigd van:
r = mlab.csv2rec(datafile, delimiter=',', names=COL_HEADERS)
mask = ((r["dt"] >= startdate) & (r["dt"] <= enddate))
selected = r[mask]
NAAR:
r = mlab.csv2rec(datafile, delimiter=',', names=COL_HEADERS)
mask = ((r["dt"] >= startdate) and (r["dt"] <= enddate))
selected = r[mask]
Tot mijn verbazing kreeg ik de nogal cryptische foutmelding:
ValueError: De waarheidswaarde van een array met meer dan één element is
dubbelzinnig. Gebruik a.any() of a.all()
Waarom werd een soortgelijke fout niet weergegeven wanneer ik een bitsgewijze bewerking gebruik – en hoe los ik dit op?
Antwoord 1, autoriteit 100%
r
is een numpy (rec)array. Dus r["dt"] >= startdate
is ook een (boolean)
reeks. Voor numpy-arrays retourneert de bewerking &
de elementwise-en van de twee
booleaanse arrays.
De NumPy-ontwikkelaars waren van mening dat er geen algemeen bekende manier was om te evalueren
een array in booleaanse context: het kan True
betekenen als elk element is
True
, of het kan True
betekenen als alle elementen True
zijn, of True
als de array een lengte heeft die niet nul is, om maar drie mogelijkheden te noemen.
Omdat verschillende gebruikers verschillende behoeften en verschillende veronderstellingen kunnen hebben, is de
NumPy-ontwikkelaars weigerden te raden en besloten in plaats daarvan een ValueError te verhogen
telkens wanneer men een array in een booleaanse context probeert te evalueren. and
toepassen op
twee numpy-arrays zorgt ervoor dat de twee arrays worden geëvalueerd in booleaanse context (door
aanroepen van __bool__
in Python3 of __nonzero__
in Python2).
Uw originele code
mask = ((r["dt"] >= startdate) & (r["dt"] <= enddate))
selected = r[mask]
ziet er goed uit. Als u echter and
wilt, gebruik dan in plaats van a and b
(a-b).any()
of (a-b).all()
.
Antwoord 2, autoriteit 31%
Ik had hetzelfde probleem (d.w.z. indexeren met meerdere voorwaarden, hier is het het vinden van gegevens in een bepaald datumbereik). De (a-b).any()
of (a-b).all()
lijken niet te werken, althans voor mij.
Als alternatief heb ik een andere oplossing gevonden die perfect werkt voor mijn gewenste functionaliteit (De waarheidswaarde van een array met meer dan één element is dubbelzinnig bij het indexeren van een array).
In plaats van de voorgestelde code hierboven te gebruiken, zou het gebruik van een numpy.logical_and(a,b)
ook werken. Hier wil je misschien de code herschrijven als
selected = r[numpy.logical_and(r["dt"] >= startdate, r["dt"] <= enddate)]
Antwoord 3, autoriteit 22%
De reden voor de uitzondering is dat and
impliciet bool
aanroept. Eerst op de linker operand en (als de linker operand True
is) dan op de rechter operand. Dus x and y
is gelijk aan bool(x) and bool(y)
.
De bool
op een numpy.ndarray
(als het meer dan één element bevat) zal echter de uitzondering veroorzaken die je hebt gezien:
>>> 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()
De bool()
-aanroep is impliciet in and
, maar ook in if
, while
, or
, dus elk van de volgende voorbeelden zal ook mislukken:
>>> 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()
Er zijn meer functies en instructies in Python die bool
-aanroepen verbergen, bijvoorbeeld 2 < x < 10
is gewoon een andere manier om 2 < x and x < 10
. En de and
zullen bool
aanroepen: bool(2 < x) and bool(x < 10)
.
Het elementsgewijs equivalent voor and
zou de np.logical_and
functie, op dezelfde manier zou je np.logical_or
als equivalent voor or
.
Voor booleaanse arrays – en vergelijkingen zoals <
, <=
, ==
, !=
, >=
en >
op NumPy-arrays retourneren booleaanse NumPy-arrays – u kunt ook de elementgewijze bitsgewijze-functies (en operators) gebruiken : np.bitwise_and
(&
operator)
>>> 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)
en bitwise_or
(|
operator):
>>> 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)
Een volledige lijst met logische en binaire functies is te vinden in de NumPy-documentatie:
Antwoord 4
als je met pandas
werkt, loste het probleem voor mij op dat ik probeerde berekeningen uit te voeren terwijl ik NA-waarden had, de oplossing was om het volgende uit te voeren:
df = df.dropna()
En daarna de berekening die mislukte.
Antwoord 5
Dit getypte foutbericht wordt ook weergegeven terwijl een if-statement
vergelijking wordt gedaan als er een array is en bijvoorbeeld een bool of int. Zie bijvoorbeeld:
... code snippet ...
if dataset == bool:
....
... code snippet ...
Deze clausule heeft een dataset als array en bool is euhm de “open deur”… True
of False
.
In het geval dat de functie is verpakt in een try-statement
, ontvangt u met except Exception as error:
het bericht zonder zijn fouttype:
De waarheidswaarde van een array met meer dan één element is dubbelzinnig. Gebruik a.any() of a.all()
Antwoord 6
Als ik het antwoord van @ZF007 overneem, dit is geen antwoord op uw vraag als geheel, maar kan de oplossing zijn voor dezelfde fout. Ik plaats het hier omdat ik geen directe oplossing heb gevonden als een antwoord op deze foutmelding elders op Stack Overflow.
De fout verschijnt wanneer u controleert of een array leeg was of niet.
-
if np.array([1,2]): print(1)
–>ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
. -
if np.array([1,2])[0]: print(1)
–> geen ValueError, maar:if np.array([])[0]: print(1)
–>IndexError: index 0 is out of bounds for axis 0 with size 0
. -
if np.array([1]): print(1)
–> geen ValueError, maar nogmaals, het zal niet helpen bij een array met veel elementen. -
if np.array([]): print(1)
–>DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use 'array.size > 0' to check that an array is not empty.
Als je dit doet:
if np.array([]).size: print(1)
heeft de fout opgelost.
Antwoord 7
probeer dit=> numpy.array(r) of numpy.array(yourvariable) gevolgd door het commando om te vergelijken wat je maar wilt.