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

2024-11-15 08:36:00
admin
原创
19
摘要:问题描述:我想用一个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
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用