index iloc columns column python pandas dataframe boolean filtering

python - iloc - El valor de verdad de una serie es ambiguo. Utilice a.empty, a.bool(), a.item(), a.any() o a.all()



pandas select rows by condition (5)

Las declaraciones or y python requieren valores de truth . Para los pandas estos se consideran ambiguos, por lo que debe usar "bit a bit" | (o) o & (y) operaciones:

result = result[(result[''var'']>0.25) | (result[''var'']<-0.25)]

Estos están sobrecargados para este tipo de estructuras de datos para producir el elemento inteligente or (o and ).

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

La excepción se produce cuando desea obtener el bool de un 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().

Lo que golpeó fue un lugar donde el operador convirtió implícitamente los operandos a bool (usó or pero también sucede para and , if y 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 4 declaraciones, hay varias funciones de python que ocultan algunas llamadas bool (como any , all , filter , ...) normalmente no son problemáticas con pandas.Series pero para completar, quería mencionarlas.

En su caso, la excepción no es realmente útil, porque no menciona las alternativas correctas . Para and y or puedes usar (si quieres comparaciones basadas en elementos):

  • 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 los operadores, asegúrese de establecer sus paréntesis correctamente debido a la precedencia del operador .

Hay varias funciones lógicas numpy que deberían funcionar en pandas.Series .

Las alternativas mencionadas en la Excepción son más adecuadas si la encontró al hacer if o while . En breve explicaré cada uno de estos:

  • Si desea verificar si su Serie está vacía :

    >>> x = pd.Series([]) >>> x.empty True >>> x = pd.Series([1]) >>> x.empty False

    Python normalmente interpreta la longitud de los contenedores (como list , tuple , ...) como valor de verdad si no tiene una interpretación booleana explícita. Entonces, si desea la comprobación similar a Python, puede hacer: if x.size o if not x.empty lugar de if x .

  • Si su Series contiene uno y solo 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 verificar si todo o algún elemento es cero, no está vacío o no es falso:

    >>> 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

Tener problemas para filtrar el marco de datos de resultados con una condición or . Quiero que mi resultado df extraiga todos los valores var columna que estén por encima de 0.25 y por debajo de -0.25.

Esta lógica a continuación me da un valor de verdad ambiguo, sin embargo, funciona cuando divido este filtrado en dos operaciones separadas. ¿Que está sucediendo aquí? no estoy seguro de dónde usar el sugerido a.empty(), a.bool(), a.item(),a.any() or a.all() .

result = result[(result[''var'']>0.25) or (result[''var'']<-0.25)]


Los pandas usan bitwise ''&'' ''|'' y cada condición debe estar envuelta en un ''()''

Por ejemplo, siguientes trabajos

data_query = data[(data[''year''] >= 2005) & (data[''year''] <= 2010)]

Pero la misma consulta sin los corchetes adecuados no

data_query = data[(data[''year''] >= 2005 & data[''year''] <= 2010)]


O, alternativamente, puede usar el módulo Operador. Información más detallada está aquí Documentos de Python

import operator import numpy as np import pandas as pd np.random.seed(0) df = pd.DataFrame(np.random.randn(5,3), columns=list(''ABC'')) df.loc[operator.or_(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.4438


Para lógica booleana, use & 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 lo que está sucediendo, obtienes una columna de booleanos para cada comparación, por ej.

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 devueltas. Es por eso que la lógica de unión es ambigua. Usando and / or trata cada columna por separado, por lo que primero debe reducir esa columna a un solo valor booleano. Por ejemplo, para ver si algún valor o todos los valores en 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 Indización booleana en los documentos.


Esta excelente respuesta explica muy bien lo que está sucediendo y brinda una solución. Me gustaría agregar otra solución que podría ser adecuada en casos similares: utilizando el método de query :

result = result.query("(var > 0.25) or (var < -0.25)")

Ver también http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-query .

(Algunas pruebas con un marco de datos con el que estoy trabajando actualmente sugieren que este método es un poco más lento que usar los operadores bit a bit en series de booleanos: 2 ms frente a 870 µs)

Una advertencia : al menos una situación en la que esto no es sencillo es cuando los nombres de columna son expresiones de python. Tenía columnas denominadas WT_38hph_IP_2 , WT_38hph_input_2 y log2(WT_38hph_IP_2/WT_38hph_input_2) y quería realizar la siguiente consulta: "(log2(WT_38hph_IP_2/WT_38hph_input_2) > 1) and (WT_38hph_IP_2 > 20)"

Obtuve la siguiente cascada de excepciones:

  • KeyError: ''log2''
  • UndefinedVariableError: name ''log2'' is not defined
  • ValueError: "log2" is not a supported function

Supongo que esto sucedió porque el analizador de consultas estaba tratando de hacer algo de las dos primeras columnas en lugar de identificar la expresión con el nombre de la tercera columna.

here se propone una posible solución alternativa.