Истинностное значение ряда неоднозначно. Использовать.пустая.типа bool(), а.пункт(), а.любой() или.все()
возникли проблемы с фильтрацией моего результата dataframe с or
состояние. Я хочу, чтобы мой результат df
для извлечения всех столбцов _var_
ценности, которые выше 0,25 и ниже -0.25. Эта логика ниже дает мне неоднозначное значение истины, однако оно работает, когда я разделяю эту фильтрацию на две отдельные операции. Что здесь происходит? не уверен, где использовать предложенный a.empty(), a.bool(), a.item(),a.any() or a.all()
.
result = result[(result['var']>0.25) or (result['var']<-0.25)]
4 ответа:
The
or
иand
операторы python требуютtruth
-значения. Ибоpandas
они считаются неоднозначными, поэтому вы должны использовать "побитовое"|
(или) или&
(и) операции:result = result[(result['var']>0.25) | (result['var']<-0.25)]
они перегружены для такого рода структур данных, чтобы дать элементарный
or
(илиand
).
просто чтобы добавить еще несколько пояснений к этому утверждению:
исключение выдается, когда вы хотите получить
bool
а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().
то, что вы попали было место, где оператор имплицитно преобразовать операнды
bool
(используетсяor
но это также происходит дляand
,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().
помимо этих 4 операторов есть несколько функций python, которые скрывают некоторые
bool
вызовов (какany
,all
,filter
, ...) это обычно не проблематично сpandas.Series
но для полноты картины я хотел сказать эти.
в вашем случае исключение не очень полезно, потому что оно не упоминает право альтернативы. Ибо
and
иor
вы можете использовать (если вы хотите поэлементного сравнения):
>>> import numpy as np >>> np.logical_or(x, y)
или просто
|
оператор:>>> x | y
>>> np.logical_and(x, y)
или просто
&
оператор:>>> x & y
если вы используете операторы, то убедитесь, что вы правильно расставленные скобки из-за приоритет оператора.
здесь несколько логических функций numpy, который должны работы на
pandas.Series
.
альтернативы, упомянутые в исключении, более подходят, если вы столкнулись с ним при выполнении
if
илиwhile
. Я коротко объясню каждый из них эти:
если вы хотите проверить, если ваша серия пустой:
>>> x = pd.Series([]) >>> x.empty True >>> x = pd.Series([1]) >>> x.empty False
Python обычно интерпретирует
len
ГТХ контейнеров (например,list
,tuple
, ...) как истинностное значение, если оно не имеет явной булевой интерпретации. Поэтому, если вы хотите проверить python-like, вы можете сделать:if x.size
илиif not x.empty
вместоif x
.если
Series
содержит один и только один boolean значение:>>> x = pd.Series([100]) >>> (x > 50).bool() True >>> (x < 50).bool() False
если вы хотите проверить первый и единственный элемент из вашей серии (например
.bool()
но работает даже для не логического содержимого):>>> x = pd.Series([100]) >>> x.item() 100
если вы хотите проверить, если все или любой элемент не ноль, не пустое или нет-ложно:
>>> 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
для логической логики используйте
&
и|
.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
чтобы увидеть, что происходит, вы получаете столбец логических значений для каждого сравнения, например,
df.C > 0.25 0 True 1 False 2 False 3 True 4 True Name: C, dtype: bool
когда у вас есть несколько критериев, вы получите несколько столбцов, возвращаемых. Вот почему логика соединения неоднозначна. Используя
and
илиor
обрабатывает каждый столбец отдельно, поэтому сначала необходимо уменьшить этот столбец до одного логического значения. Например, чтобы увидеть, есть ли какое-либо значение или все значения в каждом из столбцы-это правда.# 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
один извилистый способ достичь того же самого-это сжать все эти столбцы вместе и выполнить соответствующую логику.
>>> 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
для получения более подробной информации см. Логическое Индексации в документации.
или, в качестве альтернативы, вы можете использовать модуль оператора. Более подробная информация здесь Python docs
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
это отличный ответ очень хорошо объясняет, что происходит, и обеспечивает решение. Я хотел бы добавить еще одно решение, которое может быть подходящим в подобных случаях: используя
query
способ:result = result.query("(var > 0.25) or (var < -0.25)")
Смотрите также http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-query.
(некоторые тесты с фреймом данных, с которым я сейчас работаю, предполагают, что этот метод немного медленнее, чем использование побитовые операторы на рядах булевых значений: 2 мс против 870 МКС)
предупреждение: по крайней мере, одна ситуация, когда это не просто, когда имена столбцов оказываются выражениями python. У меня были столбцы с именем
WT_38hph_IP_2
,WT_38hph_input_2
иlog2(WT_38hph_IP_2/WT_38hph_input_2)
и хотел выполнить следующий запрос:"(log2(WT_38hph_IP_2/WT_38hph_input_2) > 1) and (WT_38hph_IP_2 > 20)"
я получил следующее исключение каскад:
KeyError: 'log2'
UndefinedVariableError: name 'log2' is not defined
ValueError: "log2" is not a supported function
Я думаю, это произошло потому, что анализатор запросов пытался сделать что-то из первых двух столбцов вместо идентификации выражения с именем третьего столбца.
возможное решение предложил!--38-->здесь.