oba*_*abs 286 python filtering boolean dataframe pandas
问题是使用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)]
Run Code Online (Sandbox Code Playgroud)
MSe*_*ert 454
在or
和and
蟒蛇语句需要truth
-值.因为pandas
这些被认为是不明确的,所以你应该使用"按位" |
(或)或&
(和)操作:
result = result[(result['var']>0.25) | (result['var']<-0.25)]
Run Code Online (Sandbox Code Playgroud)
对于这些类型的数据结构,这些都是重载的,以产生元素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().
Run Code Online (Sandbox Code Playgroud)
你击中的是一个操作符隐式将操作数转换为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().
Run Code Online (Sandbox Code Playgroud)
除了这些4个报表有几个Python函数的隐藏一些bool
调用(如any
,all
,filter
,...),这些都是通常没有问题与pandas.Series
而是完整性我想提一提这些.
在您的情况下,异常并不真正有用,因为它没有提到正确的替代方案.对于and
和or
你可以使用(如果你想要元素比较):
>>> import numpy as np
>>> np.logical_or(x, y)
Run Code Online (Sandbox Code Playgroud)
或者只是|
操作员:
>>> x | y
Run Code Online (Sandbox Code Playgroud)>>> np.logical_and(x, y)
Run Code Online (Sandbox Code Playgroud)
或者只是&
操作员:
>>> x & y
Run Code Online (Sandbox Code Playgroud)如果您正在使用运算符,请确保由于运算符优先级而正确设置括号.
有几个逻辑numpy的功能,它应该工作的pandas.Series
.
如果你在做if
或时遇到它,那么Exception中提到的替代方案更适合while
.我将简要解释其中的每一个:
如果要检查系列是否为空:
>>> x = pd.Series([])
>>> x.empty
True
>>> x = pd.Series([1])
>>> x.empty
False
Run Code Online (Sandbox Code Playgroud)
如果没有明确的布尔解释,Python通常会将len
容器的gth(例如list
,tuple
...)解释为真值.因此,如果你想要类似python的检查,你可以这样做:if x.size
或者if not x.empty
代替if x
.
如果您Series
包含一个且只包含一个布尔值:
>>> x = pd.Series([100])
>>> (x > 50).bool()
True
>>> (x < 50).bool()
False
Run Code Online (Sandbox Code Playgroud)如果你想检查你的系列的第一个也是唯一的一个项目(比如.bool()
但是对于不是布尔内容也可以):
>>> x = pd.Series([100])
>>> x.item()
100
Run Code Online (Sandbox Code Playgroud)如果你想检查所有或任何项目是否为零,不是空或不是假:
>>> 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
Run Code Online (Sandbox Code Playgroud)Ale*_*der 31
对于布尔逻辑,请使用&
和|
.
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
Run Code Online (Sandbox Code Playgroud)
要了解发生了什么,每个比较都会得到一列布尔值,例如
df.C > 0.25
0 True
1 False
2 False
3 True
4 True
Name: C, dtype: bool
Run Code Online (Sandbox Code Playgroud)
如果您有多个条件,则会返回多个列.这就是连接逻辑不明确的原因.分别使用and
或or
处理每个列,因此首先需要将该列减少为单个布尔值.例如,要查看每列中的任何值或所有值是否为True.
# 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
Run Code Online (Sandbox Code Playgroud)
实现相同目标的一种复杂方法是将所有这些列压缩在一起,并执行适当的逻辑.
>>> 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
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参阅文档中的布尔索引.
Ynj*_*jmh 17
对于初学者在 Pandas 中设置多个条件时,这是一个很常见的问题。一般来说,有两种可能的情况导致此错误:
\n条件 1:Python 运算符优先级
\n有一段布尔索引 | 索引和选择数据 \xe2\x80\x94 pandas 文档解释了这一点:
\n\n\n另一个常见的操作是使用布尔向量来过滤数据。运算符是:
\n|
foror
、&
forand
和~
fornot
。这些必须使用括号进行分组。\n
df[\'A\'] > 2 & df[\'B\'] < 3
默认情况下,Python 将计算诸如之类的表达式df[\'A\'] > (2 & df[\'B\']) < 3
,而所需的计算顺序是(df[\'A\'] > 2) & (df[\'B\'] < 3)
。
# Wrong\ndf[\'col\'] < -0.25 | df[\'col\'] > 0.25\n\n# Right\n(df[\'col\'] < -0.25) | (df[\'col\'] > 0.25)\n
Run Code Online (Sandbox Code Playgroud)\n有一些可能的方法可以去掉括号,我将在稍后介绍。
\n情况2:不正确的操作符/语句
\n正如前面的引用中所解释的,您需要使用|
for or
、&
forand
和~
for not
。
# Wrong\n(df[\'col\'] < -0.25) or (df[\'col\'] > 0.25)\n\n# Right\n(df[\'col\'] < -0.25) | (df[\'col\'] > 0.25)\n
Run Code Online (Sandbox Code Playgroud)\n另一种可能的情况是您在if
语句中使用布尔系列。
# Wrong\nif pd.Series([True, False]):\n pass\n
Run Code Online (Sandbox Code Playgroud)\n很明显,Pythonif
语句接受类似布尔的表达式,而不是 Pandas Series。您应该使用pandas.Series.any
错误消息中列出的 或 方法将 Series 转换为您需要的值。
例如:
\n# Right\nif df[\'col\'].eq(0).all():\n # If you want all column values equal to zero\n print(\'do something\')\n\n# Right\nif df[\'col\'].eq(0).any():\n # If you want at least one column value equal to zero\n print(\'do something\')\n
Run Code Online (Sandbox Code Playgroud)\n我们先来说说第一种情况下转义括号的方法。
\n使用 Pandas 数学函数
\nPandas定义了很多数学函数,包括比较,如下:
\npandas.Series.lt()
小于;pandas.Series.gt()
对于大于;pandas.Series.le()
对于小于和等于;pandas.Series.ge()
为更大且相等;pandas.Series.ne()
对于不等于;pandas.Series.eq()
对于平等;结果,您可以使用
\ndf = df[(df[\'col\'] < -0.25) | (df[\'col\'] > 0.25)]\n\n# is equal to\n\ndf = df[df[\'col\'].lt(-0.25) | df[\'col\'].gt(0.25)]\n
Run Code Online (Sandbox Code Playgroud)\n如果要选择两个值之间的行,可以使用pandas.Series.between
:
df[\'col].between(left, right)
等于(left <= df[\'col\']) & (df[\'col\'] <= right)
;df[\'col].between(left, right, inclusive=\'left)
等于(left <= df[\'col\']) & (df[\'col\'] < right)
;df[\'col].between(left, right, inclusive=\'right\')
等于(left < df[\'col\']) & (df[\'col\'] <= right)
;df[\'col].between(left, right, inclusive=\'neither\')
等于(left < df[\'col\']) & (df[\'col\'] < right)
;df = df[(df[\'col\'] > -0.25) & (df[\'col\'] < 0.25)]\n\n# is equal to\n\ndf = df[df[\'col\'].between(-0.25, 0.25, inclusive=\'neither\')]\n
Run Code Online (Sandbox Code Playgroud)\n之前引用的文档有一章“query()
方法”很好地解释了这一点。
pandas.DataFrame.query()
可以帮助您选择带有条件字符串的 DataFrame。在查询字符串中,您可以使用按位运算符 (&
和|
) 及其布尔表兄弟 (and
和or
)。此外,您可以省略括号,但出于可读性原因我不建议这样做。
df = df[(df[\'col\'] < -0.25) | (df[\'col\'] > 0.25)]\n\n# is equal to\n\ndf = df.query(\'col < -0.25 or col > 0.25\')\n
Run Code Online (Sandbox Code Playgroud)\npandas.DataFrame.eval()
评估描述 DataFrame 列操作的字符串。因此,我们可以使用这个方法来构建我们的多个条件。语法与 相同pandas.DataFrame.query()
。
df = df[(df[\'col\'] < -0.25) | (df[\'col\'] > 0.25)]\n\n# is equal to\n\ndf = df[df.eval(\'col < -0.25 or col > 0.25\')]\n
Run Code Online (Sandbox Code Playgroud)\npandas.DataFrame.query()
并且pandas.DataFrame.eval()
可以做比我在这里描述的更多的事情。建议您阅读他们的文档并享受其中的乐趣。
或者,您也可以使用操作员模块.更详细的信息在这里是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
Run Code Online (Sandbox Code Playgroud)
这个出色的答案很好地解释了正在发生的事情并提供了解决方案。我想添加另一个可能适合类似情况的解决方案:使用以下query
方法:
df = df.query("(col > 0.25) or (col < -0.25)")\n
Run Code Online (Sandbox Code Playgroud)\n另请参见索引和选择数据。
\n(对我当前正在使用的数据帧进行的一些测试表明,此方法比在一系列布尔值上使用按位运算符要慢一些:2\xc2\xa0ms 与 870\xc2\xa0\xc2\xb5s)
\n一条警告:至少有一种情况并不简单,那就是列名恰好是 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)"
我获得了以下异常级联:
\nKeyError: \'log2\'
UndefinedVariableError: name \'log2\' is not defined
ValueError: "log2" is not a supported function
我猜发生这种情况是因为查询解析器试图从前两列中获取某些内容,而不是使用第三列的名称来标识表达式。
\n这里提出了一种可能的解决方法。
\n小智 6
好吧熊猫使用按位'&''|' 并且每个条件都应该用'()'包装
例如以下作品
data_query = data[(data['year'] >= 2005) & (data['year'] <= 2010)]
Run Code Online (Sandbox Code Playgroud)
但是没有适当括号的相同查询不会
data_query = data[(data['year'] >= 2005 & data['year'] <= 2010)]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
491789 次 |
最近记录: |