
Dans NumPy et pandas, l’utilisation de numpy.ndarray ou pandas.DataFrame dans des expressions conditionnelles ou et, ou des opérations peut générer une erreur.
ValueError: The truth value of an array with more than one element is ambiguous.
ValueError: The truth value of a Series is ambiguous.
Cet article décrit les causes de cette erreur et comment la corriger.
- Cause première
- Utiliser tout(), tout(), taille
- Utilisez &, |, ~ au lieu de and, or, not
- Utilisez &, |, ~ pour les opérations booléennes/au niveau des éléments
- Les parenthèses sont requises pour plusieurs expressions conditionnelles
- Pour 1 ou 0 éléments
- Pour pandas.DataFrame, pandas.Series
Dans la plupart des cas, notez les deux points suivants.
- Utilisez &, |, ~ au lieu de and, or, not.
- et, ou, ne pas vérifier si l’objet lui-même est vrai ou faux.
- &, |, ~ effectuent des opérations booléennes/au niveau des éléments.
- Lorsque vous combinez plusieurs expressions, placez chaque expression entre parenthèses ().
- &, | ont une priorité plus élevée que les opérateurs de comparaison (tels que <).
Le concept est le même pour numpy.ndarray, pandas.DataFrame et pandas.Series.
Dans l’exemple de code suivant, NumPy est la version 1.17.3 et pandas est la version 0.25.1. Notez que différentes versions peuvent se comporter différemment.
ValueError : la valeur de vérité d’un tableau avec plus d’un élément est ambiguë.
L’utilisation de numpy.ndarray de bool dans des expressions conditionnelles or and, or, not operations génère une erreur.
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()
Les cas de pandas.DataFrame et pandas.Series sont décrits ci-dessous.
Cause première
En Python, les objets et les expressions sont évalués comme des valeurs booléennes (True, False) dans les expressions conditionnelles and and, or, not operations.
Par exemple, si une liste est vide (le nombre d’éléments est 0), elle est évaluée comme False, sinon comme True.
print(bool([0, 1, 2]))
# True
print(bool([]))
# False
print(not [0, 1, 2])
# False
print(not [])
# True
L’évaluation de numpy.ndarray en tant que valeur booléenne génère une erreur.
# bool(a_bool)
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Comme le mot « ambigu » l’indique, c’est ambigu ce que vous voulez vérifier Vrai ou Faux, l’objet lui-même ou chaque élément.
Utiliser tout(), tout(), taille
Si vous souhaitez vérifier True ou False pour l’objet lui-même, utilisez all() ou any() comme indiqué dans le message d’erreur.
all() renvoie True si tous les éléments sont True, any() renvoie True si au moins un élément est True.
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
De plus, vous pouvez obtenir le nombre total d’éléments avec l’attribut size et vérifier si numpy.ndarray est vide ou non.
print(a_bool.size)
# 3
print(a_bool.size == 0)
# False
Utilisez &, |, ~ au lieu de and, or, not
Utilisez &, |, ~ pour les opérations booléennes/au niveau des éléments
Si vous souhaitez effectuer des opérations AND, OR, NOT au niveau des éléments, utilisez &, |, ~ au lieu de and, or, not. ^ (XOR) est également disponible.
Pour numpy.ndarray de bool, les opérateurs &, |, ~ et ^ effectuent par élément AND, OR, NOT et XOR.
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]
Notez que &, | et ~ sont utilisés pour les opérations au niveau du bit sur les valeurs entières en Python.
Pour numpy.ndarray d’entier int, ils effectuent des opérations binaires élément par élément.
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]
et, ou, non et &, |, ~ sont facilement confondus.
et, ou, ne pas vérifier si l’objet lui-même est vrai ou faux. D’autre part, & et | sont utilisés pour les opérations au niveau du bit pour les valeurs entières et les opérations au niveau des éléments pour numpy.ndarray comme décrit ci-dessus, et les opérations de définition pour set.
Rappelez-vous que les mots anglais and et or sont souvent utilisés sous la forme if A et B:, et les symboles & et | sont utilisés dans d’autres opérations mathématiques.
Les parenthèses sont requises pour plusieurs expressions conditionnelles
Une opération de comparaison sur numpy.ndarray renvoie un numpy.ndarray de bool.
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]]
Comme mentionné ci-dessus, pour calculer AND ou OR pour chaque élément de ces numpy.ndarray, utilisez & ou | au lieu de et ou ou. Lorsque vous combinez plusieurs conditions avec & ou |, il est nécessaire de placer chaque expression conditionnelle entre parenthèses ().
# 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()
C’est parce que & et | ont une priorité plus élevée que les opérateurs de comparaison (tels que <).
L’exemple ci-dessus fonctionnerait comme suit.
# 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()
Chaque expression conditionnelle doit être placée entre parenthèses ().
print((a > 3) & (a % 2 == 0))
# [[False False False False]
# [ True False True False]
# [ True False True False]]
Notez que les opérations de comparaison sur de nombreux objets autres que numpy.ndarray renvoient True ou False.
x = 10
print(x > 3)
# True
print(x % 2 == 1)
# False
et et ou sont utilisés pour les opérations booléennes de Vrai et Faux. Étant donné que and et or ont une priorité inférieure aux opérateurs de comparaison (tels que <), il n’y a pas d’erreur sans parenthèses dans ce cas. Bien sûr, les parenthèses sont également acceptables.
print(x > 3 or x % 2 == 1)
# True
print((x > 3) or (x % 2 == 1))
# True
Pour 1 ou 0 éléments
Si le nombre d’éléments est un ou zéro, comme indiqué par le message d’erreur « plus d’un élément », aucune erreur n’est générée.
ValueError : la valeur de vérité d’un tableau avec plus d’un élément est ambiguë.
Si le nombre d’éléments est un, la valeur de l’élément est évaluée comme une valeur booléenne. Par exemple, si l’élément est un entier int, il vaut False s’il vaut 0 et True sinon.
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
et et ou renvoient des objets de gauche ou de droite au lieu de True ou False.
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]
& et | renvoie ET et OU élément par élément.
print(b_single & c_single)
# [0]
print(b_single | c_single)
# [3]
not renvoie NOT élément par élément. ~ renvoie élément par élément ~ (pour les entiers signés, ~x renvoie -(x + 1)).
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]
Si le nombre d’éléments est nul, un avertissement (DeprecationWarning) est émis.
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.
Il indique qu’il générera une erreur à l’avenir (l’exemple ci-dessus est la version 1.17.3), il est donc préférable d’utiliser la taille comme l’indique le message.
Pour pandas.DataFrame, pandas.Series
Pour pandas.DataFrame, comme avec numpy.ndarray, utilisez & ou | pour les opérations élément par élément, et placez les multiples conditions entre parenthèses ().
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
Des erreurs sont générées si vous utilisez et/ou omettez des parenthèses ().
# 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().
Les opérations au niveau du bit avec des valeurs scalaires sont également possibles.
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
Le décalage de bits <<, >> ne peut pas être utilisé.
# print(df << 1)
# TypeError: unsupported operand type(s) for <<: 'DataFrame' and 'int'
# print(df << df)
# TypeError: unsupported operand type(s) for <<: 'DataFrame' and 'DataFrame'
Les méthodes all() et any() sont également fournies, mais notez que la valeur par défaut est axis=0 contrairement à numpy.ndarray. Si vous souhaitez couvrir des éléments entiers, utilisez 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
Les attributs vide et taille sont également fournis.
print(df.empty)
# False
df_empty = pd.DataFrame()
print(df_empty.empty)
# True
print(df.size)
# 12
print(df_empty.size)
# 0
Il en va de même pour pandas.Series.
pandas.Series of bool est utilisé pour sélectionner des lignes en fonction des conditions. Comme numpy.ndarray et pandas.DataFrame, vous devez utiliser &, |, ~ et parenthèses ().
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