El valor de verdad de una Serie es ambiguo. Utilice a.empty, a.bool(), a.item(), a.any() o a.all()
Quiero filtrar mi marco de datos con una or
condición para mantener las filas con los valores de una columna en particular que están fuera del rango [-0.25, 0.25]
. Lo intenté:
df = df[(df['col'] < -0.25) or (df['col'] > 0.25)]
Pero me sale el error:
ValueError: el valor de verdad de una serie es ambiguo. Utilice a.empty, a.bool(), a.item(), a.any() o a.all().
Las declaraciones or
y and
de Python requieren valores de verdad . Para los pandas, estos se consideran ambiguos, por lo que debes usar operaciones "bit a bit" |
(o) o (y):&
df = df[(df['col'] < -0.25) | (df['col'] > 0.25)]
Estos están sobrecargados para que este tipo de estructuras de datos produzcan elementos or
o and
.
Solo para agregar alguna explicación más a esta declaración:
La excepción se produce cuando se desea obtener el bool
de a pandas.Series
:
>>> import pandas as pd
>>> x = pd.Series([1])
>>> bool(x)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
Llegaste a un lugar donde el operador convirtió implícitamente los operandos bool
(usaste or
pero también sucede con and
y ) if
:while
>>> x or x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> x and x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> if x:
... print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> while x:
... print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
Además de estas cuatro declaraciones, hay varias funciones de Python que ocultan algunas bool
llamadas (como any
, all
, filter
, ...). Normalmente no son problemáticos pandas.Series
, pero para completar quería mencionarlos.
En su caso, la excepción no es realmente útil porque no menciona las alternativas correctas . Para and
y or
, si desea realizar comparaciones entre elementos, puede utilizar:
numpy.logical_or
:>>> import numpy as np >>> np.logical_or(x, y)
o simplemente el
|
operador:>>> x | y
numpy.logical_and
:>>> np.logical_and(x, y)
o simplemente el
&
operador:>>> x & y
Si está utilizando operadores, asegúrese de configurar los paréntesis correctamente debido a la precedencia de los operadores .
Hay varias funciones lógicas de NumPy que deberían funcionar pandas.Series
.
Las alternativas mencionadas en la Excepción son más adecuadas si las encontró al hacer if
o while
. En breve explicaré cada uno de estos:
Si desea comprobar si su serie está vacía :
>>> x = pd.Series([]) >>> x.empty True >>> x = pd.Series([1]) >>> x.empty False
Python normalmente interpreta el
len
gésimo de los contenedores (comolist
,tuple
, ...) como valor de verdad si no tiene una interpretación booleana explícita. Entonces, si desea realizar una verificación similar a la de Python, puede hacer:if x.size
oif not x.empty
en lugar deif x
.Si
Series
contiene uno y sólo un valor booleano:>>> x = pd.Series([100]) >>> (x > 50).bool() True >>> (x < 50).bool() False
Si desea verificar el primer y único elemento de su serie (como
.bool()
, pero funciona incluso para contenidos no booleanos):>>> x = pd.Series([100]) >>> x.item() 100
Si desea comprobar si todos o alguno de los elementos no son cero, no están vacíos o no son falsos:
>>> x = pd.Series([0, 1, 2]) >>> x.all() # Because one element is zero False >>> x.any() # because one (or more) elements are non-zero True
Pandas usa bit a bit &
|
. Además, cada condición debe estar envuelta en su interior ( )
.
Esto funciona:
data_query = data[(data['year'] >= 2005) & (data['year'] <= 2010)]
Pero la misma consulta sin paréntesis no:
data_query = data[(data['year'] >= 2005 & data['year'] <= 2010)]
Para lógica booleana, utilice &
y |
.
np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))
>>> df
A B C
0 1.764052 0.400157 0.978738
1 2.240893 1.867558 -0.977278
2 0.950088 -0.151357 -0.103219
3 0.410599 0.144044 1.454274
4 0.761038 0.121675 0.443863
>>> df.loc[(df.C > 0.25) | (df.C < -0.25)]
A B C
0 1.764052 0.400157 0.978738
1 2.240893 1.867558 -0.977278
3 0.410599 0.144044 1.454274
4 0.761038 0.121675 0.443863
Para ver qué está sucediendo, obtienes una columna de valores booleanos para cada comparación, por ejemplo,
df.C > 0.25
0 True
1 False
2 False
3 True
4 True
Name: C, dtype: bool
Cuando tenga varios criterios, obtendrá varias columnas. Por eso la lógica de unión es ambigua. Utiliza and
o or
trata cada columna por separado, por lo que primero debe reducir esa columna a un único valor booleano. Por ejemplo, para ver si algún valor o todos los valores de cada una de las columnas es Verdadero.
# Any value in either column is True?
(df.C > 0.25).any() or (df.C < -0.25).any()
True
# All values in either column is True?
(df.C > 0.25).all() or (df.C < -0.25).all()
False
Una forma complicada de lograr lo mismo es comprimir todas estas columnas y realizar la lógica adecuada.
>>> df[[any([a, b]) for a, b in zip(df.C > 0.25, df.C < -0.25)]]
A B C
0 1.764052 0.400157 0.978738
1 2.240893 1.867558 -0.977278
3 0.410599 0.144044 1.454274
4 0.761038 0.121675 0.443863
Para obtener más detalles, consulte Indexación booleana en la documentación.