El valor de verdad de una Serie es ambiguo. Utilice a.empty, a.bool(), a.item(), a.any() o a.all()

Resuelto obabs asked hace 8 años • 14 respuestas

Quiero filtrar mi marco de datos con una orcondició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().

obabs avatar Apr 29 '16 00:04 obabs
Aceptado

Las declaraciones ory andde 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 oro and.


Solo para agregar alguna explicación más a esta declaración:

La excepción se produce cuando se desea obtener el boolde 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 orpero también sucede con andy ) 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 boolllamadas (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 andy 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 ifo 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 lengésimo de los contenedores (como list, 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.sizeo if not x.emptyen lugar de if x.

  • Si Seriescontiene 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
    
MSeifert avatar Apr 28 '2016 17:04 MSeifert

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)]
Nipun avatar Sep 11 '2019 22:09 Nipun

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 ando ortrata 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.

Alexander avatar Apr 28 '2016 18:04 Alexander