系列的真值不明确。请使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()
- 2024-11-15 08:36:00
- admin 原创
- 20
问题描述:
我想用一个or
条件过滤我的数据框以保留具有特定列的值超出范围的行[-0.25, 0.25]
。我试过了:
df = df[(df['col'] < -0.25) or (df['col'] > 0.25)]
但我收到了错误:
ValueError:Series 的真值不明确。请使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()。
解决方案 1:
Python语句or
和and
需要真值。对于 pandas 来说,这些被视为模棱两可的,因此您应该使用“按位” |
(或)或&
(与)运算:
df = df[(df['col'] < -0.25) | (df['col'] > 0.25)]
对于这些类型的数据结构,它们被重载以产生逐元素or
或and
。
只是想对这句话添加一些解释:
当您想要获取bool
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().
您遇到了一个地方,其中运算符隐式地将操作数转换为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().
除了这四个语句之外,还有几个 Python 函数隐藏了一些调用bool
(例如any
,,,,...)。这些通常不会有问题,但为了完整性,我想提一下这些。all
`filter`pandas.Series
在您的情况下,异常并没有真正帮助,因为它没有提到正确的替代方案。对于and
和or
,如果您想要逐元素比较,则可以使用:
numpy.logical_or
:
>>> import numpy as np
>>> np.logical_or(x, y)
或者简单的|
操作:
>>> x | y
numpy.logical_and
:
>>> 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
、、 ...)的 gth 解释为真值。因此,如果您想要类似 Python 的检查,您可以执行:或而不是。tuple
`if x.sizeif not x.empty
if x`
如果您的仅
Series
包含一个布尔值:
>>> 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
解决方案 2:
Pandas 使用按位&
|
。此外,每个条件都应包装在 内( )
。
这有效:
data_query = data[(data['year'] >= 2005) & (data['year'] <= 2010)]
但是没有括号的相同查询则不会:
data_query = data[(data['year'] >= 2005 & data['year'] <= 2010)]
解决方案 3:
对于布尔逻辑,使用&
和|
。
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
会分别处理每一列,因此您首先需要将该列简化为单个布尔值。例如,查看每列中的任何值或所有值是否为 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
实现同样目标的一个复杂方法是将所有这些列压缩在一起,并执行适当的逻辑。
>>> 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
有关更多详细信息,请参阅文档中的布尔索引。
解决方案 4:
这是初学者在 Pandas 中设置多个条件时经常遇到的问题。一般来说,有两种可能的情况会导致此错误:
条件 1:Python 运算符优先级
布尔索引 | 索引和选择数据 - pandas 文档中有一段解释了这一点:
另一个常见操作是使用布尔向量来过滤数据。运算符包括:
|
foror
、&
forand
和~
fornot
。这些必须使用括号分组。
df['A'] > 2 & df['B'] < 3
默认情况下,Python 将评估诸如这样的表达式df['A'] > (2 & df['B']) < 3
,而所需的评估顺序是(df['A'] > 2) & (df['B'] < 3)
。
# Wrong
df['col'] < -0.25 | df['col'] > 0.25
# Right
(df['col'] < -0.25) | (df['col'] > 0.25)
有一些可能的方法可以去掉括号,我将在后面介绍。
情况 2:不正确的操作符/语句
正如前面的引文所解释的,您需要使用|
for or
、&
forand
和~
for not
。
# Wrong
(df['col'] < -0.25) or (df['col'] > 0.25)
# Right
(df['col'] < -0.25) | (df['col'] > 0.25)
另一种可能的情况是您在语句中使用布尔系列if
。
# Wrong
if pd.Series([True, False]):
pass
很明显,Pythonif
语句接受的是布尔表达式,而不是 Pandas Series。你应该使用pandas.Series.any
错误消息中列出的方法将 Series 转换为所需的值。
例如:
# Right
if df['col'].eq(0).all():
# If you want all column values equal to zero
print('do something')
# Right
if df['col'].eq(0).any():
# If you want at least one column value equal to zero
print('do something')
我们来讨论一下第一种情况下转义括号的方法。
使用 Pandas 数学函数
Pandas 定义了很多数学函数,包括比较函数,如下:
* `pandas.Series.lt()`少于;**
* `pandas.Series.gt()`大于;**
* `pandas.Series.le()`为*少而平等*;
* `pandas.Series.ge()`表示*大于和等于*;
* `pandas.Series.ne()`表示*不等于*;
* `pandas.Series.eq()`为*相等*;因此,您可以使用
df = df[(df['col'] < -0.25) | (df['col'] > 0.25)]
# is equal to
df = df[df['col'].lt(-0.25) | df['col'].gt(0.25)]
使用
pandas.Series.between()
如果要选择两个值之间的行,可以使用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)]
# is equal to
df = df[df['col'].between(-0.25, 0.25, inclusive='neither')]
使用
pandas.DataFrame.query()
之前引用的文档有一章“query()
方法”很好地解释了这一点。
pandas.DataFrame.query()
可以帮助您使用条件字符串选择 DataFrame。在查询字符串中,您可以使用按位运算符(&
and |
)及其布尔运算符(and
and or
)。此外,您可以省略括号,但出于可读性原因,我不建议这样做。
df = df[(df['col'] < -0.25) | (df['col'] > 0.25)]
# is equal to
df = df.query('col < -0.25 or col > 0.25')
使用
pandas.DataFrame.eval()
pandas.DataFrame.eval()
评估描述对 DataFrame 列的操作的字符串。因此,我们可以使用此方法来构建多个条件。语法与 相同pandas.DataFrame.query()
。
df = df[(df['col'] < -0.25) | (df['col'] > 0.25)]
# is equal to
df = df[df.eval('col < -0.25 or col > 0.25')]
pandas.DataFrame.query()
并且pandas.DataFrame.eval()
可以做比我在这里描述的更多的事情。建议您阅读它们的文档并享受它们的乐趣。
解决方案 5:
或者,您也可以使用operator模块。更多详细信息请参阅 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
解决方案 6:
这个出色的答案很好地解释了正在发生的事情并提供了解决方案。我想添加另一种可能适用于类似情况的解决方案:使用query
方法:
df = df.query("(col > 0.25) or (col < -0.25)")
另请参阅索引和选择数据。
(我目前正在使用的数据框进行的一些测试表明,此方法比在一系列布尔值上使用按位运算符要慢一点: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
我猜发生这种情况是因为查询解析器试图从前两列中生成某些内容,而不是用第三列的名称来识别表达式。
这里提出了一种可能的解决方法。
解决方案 7:
如果您有多个值:
df['col'].all()
如果它只有一个值:
df['col'].item()
解决方案 8:
我在这个命令中遇到了一个错误:
if df != '':
pass
但当我将其改为这样时它就起作用了:
if df is not '':
pass
解决方案 9:
在 pandas 中,您需要使用按位运算符|
而不是or
and 。您不能简单地使用 python 中的 bool 语句。&
`and`
对于更复杂的过滤,请创建一个mask
并在数据框上应用掩码。
将所有查询放入掩码中并应用它。假设,
mask = (df["col1"]>=df["col2"]) & (stock["col1"]<=df["col2"])
df_new = df[mask]
解决方案 10:
我在 Panda 数据框中工作时遇到了同样的问题。
我已经使用过:numpy.logical_and:
在这里,我尝试选择 Id 与之匹配41d7853
且 degreee_type 不与之匹配的行Certification
。
如下所示:
display(df_degrees.loc[np.logical_and(df_degrees['person_id'] == '41d7853' , df_degrees['degree_type'] !='Certification')])
如果我尝试编写如下代码:
display(df_degrees.loc[df_degrees['person_id'] == '41d7853' and df_degrees['degree_type'] !='Certification'])
我们会得到错误:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
我已经使用过numpy.logical_and,它对我有用。
解决方案 11:
我将尝试给出三种最常见方式的基准(上面也提到过):
from timeit import repeat
setup = """
import numpy as np;
import random;
x = np.linspace(0,100);
lb, ub = np.sort([random.random() * 100, random.random() * 100]).tolist()
"""
stmts = 'x[(x > lb) * (x <= ub)]', 'x[(x > lb) & (x <= ub)]', 'x[np.logical_and(x > lb, x <= ub)]'
for _ in range(3):
for stmt in stmts:
t = min(repeat(stmt, setup, number=100_000))
print('%.4f' % t, stmt)
print()
结果:
0.4808 x[(x > lb) * (x <= ub)]
0.4726 x[(x > lb) & (x <= ub)]
0.4904 x[np.logical_and(x > lb, x <= ub)]
0.4725 x[(x > lb) * (x <= ub)]
0.4806 x[(x > lb) & (x <= ub)]
0.5002 x[np.logical_and(x > lb, x <= ub)]
0.4781 x[(x > lb) * (x <= ub)]
0.4336 x[(x > lb) & (x <= ub)]
0.4974 x[np.logical_and(x > lb, x <= ub)]
但是,*
Panda 系列不支持,并且 NumPy Array 比 pandas 数据框更快(慢约 1000 倍,见数字):
from timeit import repeat
setup = """
import numpy as np;
import random;
import pandas as pd;
x = pd.DataFrame(np.linspace(0,100));
lb, ub = np.sort([random.random() * 100, random.random() * 100]).tolist()
"""
stmts = 'x[(x > lb) & (x <= ub)]', 'x[np.logical_and(x > lb, x <= ub)]'
for _ in range(3):
for stmt in stmts:
t = min(repeat(stmt, setup, number=100))
print('%.4f' % t, stmt)
print()
结果:
0.1964 x[(x > lb) & (x <= ub)]
0.1992 x[np.logical_and(x > lb, x <= ub)]
0.2018 x[(x > lb) & (x <= ub)]
0.1838 x[np.logical_and(x > lb, x <= ub)]
0.1871 x[(x > lb) & (x <= ub)]
0.1883 x[np.logical_and(x > lb, x <= ub)]
注意:添加一行代码x = x.to_numpy()
大约需要 20 µs。
对于那些喜欢%timeit
:
import numpy as np
import random
lb, ub = np.sort([random.random() * 100, random.random() * 100]).tolist()
lb, ub
x = pd.DataFrame(np.linspace(0,100))
def asterik(x):
x = x.to_numpy()
return x[(x > lb) * (x <= ub)]
def and_symbol(x):
x = x.to_numpy()
return x[(x > lb) & (x <= ub)]
def numpy_logical(x):
x = x.to_numpy()
return x[np.logical_and(x > lb, x <= ub)]
for i in range(3):
%timeit asterik(x)
%timeit and_symbol(x)
%timeit numpy_logical(x)
print('
')
结果:
23 µs ± 3.62 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
35.6 µs ± 9.53 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
31.3 µs ± 8.9 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
21.4 µs ± 3.35 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
21.9 µs ± 1.02 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
21.7 µs ± 500 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
25.1 µs ± 3.71 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
36.8 µs ± 18.3 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
28.2 µs ± 5.97 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
解决方案 12:
我遇到了同样的错误,并且PySpark数据框停滞了几天。由于我正在比较两个字段的整数值,因此我能够通过用 0 填充 na 值来成功解决该问题。
解决方案 13:
一件小事,浪费了我的时间。
将条件(如果使用“=”、“!=”进行比较)放在括号中。如果不这样做也会引发此异常。
这将起作用:
df[(some condition) conditional operator (some conditions)]
这不会:
df[some condition conditional-operator some condition]
解决方案 14:
在我的例子中,我遇到了类型值错误,导致出现此错误。确保比较运算符被赋予了相同的数据类型元素来进行比较。
解决方案 15:
可能出现此错误的另一种情况是,当 pandas 单元包含 numpy ndarrays 并且您想要执行诸如 等比较>
时==
。
df = pd.DataFrame({'A': [np.array([1, 2]), np.array([3, 1])]})
df['A'] > 2 # <--- ValueError: The truth value of ...
一个解决方案是在执行相同的工作之前将其转换为适当的 ndarray。
np.stack(df['A']) > 2 # <--- OK
或者使用.str
访问器访问值:
df['A'].str[0] > 2 # <--- OK
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件