Истинностное значение ряда неоднозначно. Использовать.пустая.типа 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 FalsePython обычно интерпретирует
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 definedValueError: "log2" is not a supported functionЯ думаю, это произошло потому, что анализатор запросов пытался сделать что-то из первых двух столбцов вместо идентификации выражения с именем третьего столбца.
возможное решение предложил!--38-->здесь.