系列的真值不明确。请使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()

2024-11-15 08:36:00
admin
原创
252
摘要:问题描述:我想用一个or条件过滤我的数据框以保留具有特定列的值超出范围的行[-0.25, 0.25]。我试过了:df = df[(df['col'] < -0.25) or (df['col'] > 0.25)] 但我收到了错误:ValueError:Series 的真值不明确。请使用 a.emp...

问题描述:

我想用一个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语句orand需要值。对于 pandas 来说,这些被视为模棱两可的,因此您应该使用“按位” |(或)或&(与)运算:

df = df[(df['col'] < -0.25) | (df['col'] > 0.25)]

对于这些类型的数据结构,它们被重载以产生逐元素orand


只是想对这句话添加一些解释:

当您想要获取boola时会引发异常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但它也会发生在andif和上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


在您的情况下,异常并没有真正帮助,因为它没有提到正确的替代方案。对于andor,如果您想要逐元素比较,则可以使用:

  • 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.emptyif 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

当您有多个条件时,您将返回多个列。这就是连接逻辑不明确的原因。使用andor会分别处理每一列,因此您首先需要将该列简化为单个布尔值。例如,查看每列中的任何值或所有值是否为 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 文档中有一段解释了这一点:

另一个常见操作是使用布尔向量来过滤数据。运算符包括:|for or&forand~for not。这些必须使用括号分组。

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

我们来讨论一下第一种情况下转义括号的方法。

  1. 使用 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)]
  1. 使用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')]
  1. 使用pandas.DataFrame.query()

之前引用的文档有一章“query()方法”很好地解释了这一点。

pandas.DataFrame.query()可以帮助您使用条件字符串选择 DataFrame。在查询字符串中,您可以使用按位运算符(&and |)及其布尔运算符(andand or)。此外,您可以省略括号,但出于可读性原因,我不建议这样做。

df = df[(df['col'] < -0.25) | (df['col'] > 0.25)]

# is equal to

df = df.query('col < -0.25 or col > 0.25')
  1. 使用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 中,您需要使用按位运算符|而不是orand 。您不能简单地使用 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
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1259  
  IPD(Integrated Product Development)流程管理作为一种先进的产品开发管理理念和方法,在提升企业创新能力方面发挥着至关重要的作用。它打破了传统产品开发过程中部门之间的壁垒,通过整合资源、优化流程,实现产品的快速、高效开发,为企业在激烈的市场竞争中赢得优势。IPD流程管理的核心概念IPD流程...
IPD流程中PDCP是什么意思   11  
  IPD(Integrated Product Development)流程管理作为一种先进的产品开发管理模式,旨在通过整合各种资源,实现产品的高效、高质量开发。在这一过程中,团队协作无疑是成功的关键。有效的团队协作能够打破部门壁垒,促进信息共享,提升决策效率,从而确保产品开发项目顺利推进。接下来,我们将深入探讨IPD流...
IPD培训课程   9  
  IPD(Integrated Product Development)研发管理体系作为一种先进的产品开发理念和方法,在众多企业中得到了广泛应用。它旨在打破部门壁垒,整合资源,实现产品开发的高效、协同与创新。在项目周期方面,IPD研发管理体系有着深远且多维度的影响,深入剖析这些影响,对于企业优化产品开发流程、提升市场竞争...
华为IPD流程   11  
  IPD(Integrated Product Development)流程管理是一种先进的产品开发管理模式,旨在通过整合企业的各种资源,实现产品的高效、高质量开发。它涵盖了从产品概念提出到产品退市的整个生命周期,对企业的发展具有至关重要的意义。接下来将详细阐述IPD流程管理的五个阶段及其重要性。概念阶段概念阶段是IPD...
IPD概念阶段   12  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用