Skip to content

NumPy, pandas: Wie man ValueError behebt: Der Wahrheitswert … ist mehrdeutig

Python

In NumPy und Pandas kann die Verwendung von numpy.ndarray oder pandas.DataFrame in bedingten Ausdrücken oder und oder Operationen einen Fehler auslösen.

ValueError: The truth value of an array with more than one element is ambiguous.  
ValueError: The truth value of a Series is ambiguous.

Dieser Artikel korrigiert die Ursachen dieses Fehlers und wie SIE ihn beheben können.

  • Tiefere Ursache
  • Verwenden Sie all(), any(), size
  • Verwenden Sie &, |, ~ anstelle von and, or, not
    • Verwenden Sie &, |, ~ für elementweise boolesche/bitweise Operationen
    • Klammern sind für mehrere Bedingungsausdrücke erforderlich
  • Für 1 oder 0 Elemente
  • Für pandas.DataFrame, pandas.Series

Beachten Sie in den meisten Fällen die following two points.

  1. Verwenden Sie &, |, ~ anstelle von and, or, not.
    • und, oder, nicht prüfen, ob das Objekt selbst True oder False ist.
    • &, |, ~ führen elementweise boolesche/bitweise Operationen aus.
  2. Schließen Sie beim Kombinieren mehrerer Ausdrücke jeden Ausdruck in Klammern () ein.
    • &, | haben eine höhere Priorität als Vergleichsoperatoren (z. B. <).

Das Konzept ist für numpy.ndarray, pandas.DataFrame und pandas.Series dasselbe.

Im folgenden Beispielcode ist NumPy Version 1.17.3 und pandas Version 0.25.1. Beachten Sie, dass sich verschiedene Versionen unterschiedlich verhalten können.

ValueError: Der Wahrheitswert eines Arrays mit mehr als einem Element ist mehrdeutig.

Die Verwendung von numpy.ndarray of bool in Bedingungsausdrücken oder and-or-not-Operationen löst einen Fehler aus.

import numpy as np

print(np.__version__)
# 1.17.3

a_bool = np.array([True, True, True])
b_bool = np.array([True, False, False])

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

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

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

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

Die Fälle pandas.DataFrame und pandas.Series werden unten beschrieben.

Tiefere Ursache

In Python werden Objekte und Ausdrücke als boolesche Werte (True, False) in bedingten Ausdrücken und, or, not-Operationen ausgewertet.

Wenn beispielsweise eine Liste leer ist (Anzahl der Elemente ist 0), wird sie als False bewertet, andernfalls als True.

print(bool([0, 1, 2]))
# True

print(bool([]))
# False

print(not [0, 1, 2])
# False

print(not [])
# True

Das Auswerten von numpy.ndarray als Bool-Wert löst einen Fehler aus.

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

Wie das Wort „mehrdeutig“ andeutet, ist es mehrdeutig, also SIE True oder False prüfen möchten, das Objekt selbst oder jedes Element.

Verwenden Sie all(), any(), size

Wenn Sie True oder False für das Objekt selbst überprüfen möchten, verwenden Sie all() oder any(), wie in der Fehlermeldung gezeigt.

all() gibt True zurück, wenn alle Elemente True sind, any() gibt True zurück, wenn mindestens ein Element True ist.

a_bool = np.array([True, True, True])
b_bool = np.array([True, False, False])
print(a_bool.all())
# True

print(a_bool.any())
# True

print(b_bool.all())
# False

print(b_bool.any())
# True

Außerdem kann man mit dem Größen-Attribut die Gesamtzahl der Elemente abrufen und damit prüfen, ob numpy.ndarray leer ist oder nicht.

print(a_bool.size)
# 3

print(a_bool.size == 0)
# False

Verwenden Sie &, |, ~ anstelle von and, or, not

Verwenden Sie &, |, ~ für elementweise boolesche/bitweise Operationen

If SIE elementweise AND-, OR-, NOT-Operationen durchführen möchten, verwenden SIE &, |, ~ anstelle von and, or, not. ^ (XOR) ist ebenfalls verfügbar.

Für numpy.ndarray of bool führen die Operatoren &, |, ~ und ^ elementweise AND, OR, NOT und XOR aus.

a_bool = np.array([True, True, True])
b_bool = np.array([True, False, False])
print(a_bool & b_bool)
# [ True False False]

print(a_bool | b_bool)
# [ True  True  True]

print(~b_bool)
# [False  True  True]

print(a_bool ^ b_bool)
# [False  True  True]

Beachten Sie, dass &, | und ~ für bitweise Operationen mit ganzzahligen Werten in Python used Werden.

Für numpy.ndarray von integer führen sie elementweise bitweise Operationen aus.

a_int = np.array([0, 1, 3])  # [0b00 0b01 0b11]
b_int = np.array([1, 0, 2])  # [0b01 0b00 0b10]

print(a_int & b_int)
# [0 0 2]

print(a_int | b_int)
# [1 1 3]

print(a_int ^ b_int)
# [1 1 1]

print(~a_int)
# [-1 -2 -4]

and, or, not und &, |, ~ werden leicht verwechselt.

und, oder, nicht prüfen, ob das Objekt selbst True oder False ist. & und | Werden für bitweise beschriebene Operationen für ganzzahlige Werte und elementweise Operationen für numpy.ndarray wie oben und Set-Operationen für set used.

Denken Sie daran, dass die englischen Wörter und oder oft in der Form if A und B: und den Symbolen & und | used Werden in anderen mathematischen Operationen used.

Klammern sind für mehrere Bedingungsausdrücke erforderlich

One Vergleichsoperation for numpy.ndarray is a numpy.ndarray from bool back.

a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

print(a > 3)
# [[False False False False]
#  [ True  True  True  True]
#  [ True  True  True  True]]

print(a % 2 == 0)
# [[ True False  True False]
#  [ True False  True False]
#  [ True False  True False]]

Wie oben erwähnt, verwenden SIE & oder |, um UND oder ODER für jedes Element dieser numpy.ndarray zu berechnen statt und oder oder. Wenn Sie mehrere Bedingungen mit & oder | kombinieren, müssen Sie jeden Bedingungsausdruck in Klammern () setzen.

# print(a > 3 & a % 2 == 0)
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Das liegt daran, dass & und | haben eine höhere Priorität als Vergleichsoperatoren (z. B. <).

Das obige Beispiel würde wie folgt betrieben werden.

# print(a > (3 & (a % 2)) == 0)
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Jeder bedingte Ausdruck muss in Klammern () Eingeschlossen Werden.

print((a > 3) & (a % 2 == 0))
# [[False False False False]
#  [ True False  True False]
#  [ True False  True False]]

Beachten Sie, dass Vergleichsoperationen für viele andere Objekte als numpy.ndarray True oder False zurückgeben.

x = 10

print(x > 3)
# True

print(x % 2 == 1)
# False

und und oder werden für boolesche Operationen von True und False used. Da und oder eine geringere Priorität als Vergleichsoperatoren (zB <) haben, gibt es in diesem Fall keinen Fehler ohne Klammern. Natürlich sind auch Klammern zulässig.

print(x > 3 or x % 2 == 1)
# True

print((x > 3) or (x % 2 == 1))
# True

Für 1 oder 0 Elemente

Wenn die Anzahl der Elemente eins oder null ist, wie durch die Fehlermeldung „mehr als ein Element“ angezeigt wird, wird kein Fehler ausgelöst.

ValueError: Der Wahrheitswert eines Arrays mit mehr als einem Element ist mehrdeutig.

Wenn die Anzahl der Elemente eins ist, wird der Wert des Elements als Bool-Wert ermittelt. If das Element beispielsweise eine Ganzzahl int ist, ist es False, wenn es 0 ist, und andernfalls True.

a_single = np.array([0])
b_single = np.array([1])
c_single = np.array([2])

print(bool(a_single))
# False

print(bool(b_single))
# True

print(bool(c_single))
# True

und und oder geben entweder Objekte auf der linken oder rechten Seite anstelle von True oder False zurück.

print(b_single and c_single)
# [2]

print(c_single and b_single)
# [1]

print(b_single or c_single)
# [1]

print(c_single or b_single)
# [2]

& und | Elementweise UND und ODER zurückgeben.

print(b_single & c_single)
# [0]

print(b_single | c_single)
# [3]

not gibt elementweise NICHT zurück. ~ gibt elementweise ~ zurück (für ganze Zahlen mit Vorzeichen gibt ~x -(x + 1) zurück).

print(not a_single)
# True

print(not b_single)
# False

print(not c_single)
# False

print(~a_single)
# [-1]

print(~b_single)
# [-2]

print(~c_single)
# [-3]

Wenn die Anzahl der Elemente null ist, wird eine Warnung (DeprecationWarning) ausgegeben.

a_empty = np.array([])
print(a_empty)
# []

print(bool(a_empty))
# False
# 
# /usr/local/lib/python3.7/site-packages/ipykernel_launcher.py: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.
#   """Entry point for launching an IPython kernel.

Es heißt, dass es in Zukunft einen Fehler auslösen WIRD (das obige Beispiel ist Version 1.17.3), daher ist es besser, die Größe so zu verwenden, wie es in der Nachricht steht.

Für pandas.DataFrame, pandas.Series

Verwenden Sie für pandas.DataFrame wie bei numpy.ndarray & oder | für elementweise Operationen und schließen Sie sterben mehrere Bedingungen in Klammern () ein.

import pandas as pd

df = pd.DataFrame(pd.np.arange(12).reshape(3, 4), columns=['a', 'b', 'c', 'd'], index=['x', 'y', 'z'])
print(df)
#    a  b   c   d
# x  0  1   2   3
# y  4  5   6   7
# z  8  9  10  11

print((df > 3) & (df % 2 == 0))
#        a      b      c      d
# x  False  False  False  False
# y   True  False   True  False
# z   True  False   True  False

Fehler Werden ausgelöst, Wenn SIE Klammern () verwenden und/oder weglassen.

# print((df > 3) and (df % 2 == 0))
# ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

# print(df > 3 & df % 2 == 0)
# ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Auch bitweise Operationen mit skalaren Werten sind möglich.

print(df & 7)
#    a  b  c  d
# x  0  1  2  3
# y  4  5  6  7
# z  0  1  2  3

print(df | 1)
#    a  b   c   d
# x  1  1   3   3
# y  5  5   7   7
# z  9  9  11  11

Bitverschiebung <<, >> kann nicht verwendet werden.

# print(df << 1)
# TypeError: unsupported operand type(s) for <<: 'DataFrame' and 'int'

# print(df << df)
# TypeError: unsupported operand type(s) for <<: 'DataFrame' and 'DataFrame'

all()- und any()-Methoden werden ebenfalls bereitgestellt, aber beachten Sie, dass der Standardwert axis=0 ist, im Gegensatz zu numpy.ndarray. Wenn Sie ganze Elemente abdecken möchten, verwenden Sie axis=None.

print(df > 3)
#        a      b      c      d
# x  False  False  False  False
# y   True   True   True   True
# z   True   True   True   True

print((df > 3).all())
# a    False
# b    False
# c    False
# d    False
# dtype: bool

print((df > 3).all(axis=1))
# x    False
# y     True
# z     True
# dtype: bool

print((df > 3).all(axis=None))
# False

Die Attribute empty und size werden ebenfalls bereitgestellt.

print(df.empty)
# False

df_empty = pd.DataFrame()
print(df_empty.empty)
# True

print(df.size)
# 12

print(df_empty.size)
# 0

Dasselbe vergoldet für Pandas.Serie.

pandas.Series of bool WIRD used, um Zeilen gemäß Bedingungen auszuwählen. Wie bei numpy.ndarray und pandas.DataFrame müssen Sie &, |, ~ und Klammern () verwenden.

df = pd.read_csv('data/src/sample_pandas_normal.csv')
print(df)
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57
print(df['age'] < 35)
# 0     True
# 1    False
# 2     True
# 3    False
# 4     True
# 5     True
# Name: age, dtype: bool

print(~(df['state'] == 'NY'))
# 0    False
# 1     True
# 2     True
# 3     True
# 4     True
# 5    False
# Name: state, dtype: bool

print((df['age'] < 35) & ~(df['state'] == 'NY'))
# 0    False
# 1    False
# 2     True
# 3    False
# 4     True
# 5    False
# dtype: bool

df_and = df[(df['age'] < 35) & ~(df['state'] == 'NY')]
print(df_and)
#       name  age state  point
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88