您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Python-使用pd.eval()在熊猫中进行动态表达评估

Python-使用pd.eval()在熊猫中进行动态表达评估

这个答案潜入各种特性和功能的提供pd.eval,df.querydf.eval

设置 示例将涉及这些DataFrame(除非另有说明)。

注意 在所讨论的三个功能中,pd.eval最为重要。df.eval并在幕后df.query打电话 pd.eval。行为和用法在这三个功能上或多或少是一致的,有些语义上的细微变化将在后面强调。本节将介绍所有这三个功能共有的功能-包括(但不限于)允许的语法,优先级规则和关键字参数

pd.eval可以评估由变量和/或文字组成的算术表达式。这些表达式必须作为字符串传递。因此,要回答上述问题,你可以

这里要注意一些事情:

…等等。还以相同方式支持条件表达式。下面的语句都是有效表达式,将由引擎进行评估。

可以在文档中找到详细列出所有受支持功能和语法的列表。综上所述,

文档的此部分还指定了不支持的语法规则,包括set/ dict文字,if-else语句,循环和理解以及生成器表达式。

从列表中可以明显看出,你还可以传递涉及索引的表达式,例如

pd.eval解析表达式字符串以生成语法树时,支持两种不同的解析器选项:pandaspython。两者之间的主要区别通过稍有不同的优先级规则突出显示

使用认解析器pandas,重载的逐位运算符&以及|与pandas对象实现向量化ANDOR的运算符的优先级与andor。所以,

将与

而且也一样

在此,括号是必需的。通常,要这样做,需要使用parens来覆盖按位运算符的更高优先级:

没有那个,我们最终会

parser='python'如果要在评估字符串时保持与python实际运算符优先级规则的一致性,请使用。

两种类型的解析器之间的一个区别是带有listtuple节点的==and !=运算符的语义,在使用解析器时,它们的语义分别与in和相似。例如,not in'pandas'

有效,并将以与以下相同的语义运行

OTOH,pd.eval(“df1 == [1, 2, 3]”, parser=’python’)将引发NotImplementedError错误

有两个选项- numexpr认)和python。该numexpr选项使用为性能优化的numexpr后端。

使用’python’后端,对表达式的评估类似于仅将表达式传递给python的eval函数。你可以灵活地执行更多内部表达式,例如字符串操作。

不幸的是,这种方法没有提供比numexpr引擎更好的性能优势,并且几乎没有安全措施可确保不评估危险的表达式,因此请自担风险使用!’python’除非你知道自己在做什么,否则通常不建议将此选项更改为。

有时,为表达式中使用的变量提供值很有用,但当前尚未在名称空间中定义变量。你可以将字典传递给local_dict

例如,

由于thresh未定义,因此失败。但是,这可行:

当你有要从字典提供的变量时,这很有用。另外,使用’python’引擎,你可以简单地执行以下操作:

但是,这将可能是很多比使用较慢的'numexpr'发动机和传递一个字典local_dictglobal_dict。希望这应该为使用这些参数提供令人信服的论据。

这通常不是必需的,因为通常有更简单的方法可以执行此操作,但是你可以将结果分配给pd.eval实现__getitem__诸如dicts和(猜对了)DataFrames的对象。

考虑问题中的例子

要将列“ D”分配给df2,

这不是就地修改df2(但可以…继续阅读)。考虑另一个示例:

例如,如果你想将此分配回一个DataFrame,则可以使用target如下参数:

如果要在上执行就地突变df,请设置inplace=True。

如果inplace设置为没有目标,ValueError则引发a。

尽管该target参数很有趣,但你几乎不需要使用它。

如果要使用进行此操作df.eval,则可以使用涉及赋值的表达式:

注意的 一种pd.eval意外用途是以与以下方式非常相似的方式解析文字字符串ast.literal_eval:

它还可以使用’python’引擎解析嵌套列表:

以及字符串列表:

但是,问题在于长度大于100的列表:

有关此错误,原因,修复和解决方法的更多信息,请参见此处。

DataFrame.eval -与并置 pandas.eval 如上所述,在后台df.eval调用pd.eval。的v0.23源代码示出了该:

eval创建参数,进行一些验证,然后将参数传递给pd.eval

有关更多信息,你可以继续阅读:何时使用DataFrame.eval()pandas.eval()python eval()

用法差异 具有DataFrames v / s系列表达式的表达式 对于与整个DataFrame相关的动态查询,你应该首选pd.eval。例如,没有简单的方法来指定pd.eval(“df1 + df2”)调用df1.eval或时的等效项df2.eval。

一个主要区别是如何访问列。例如,要在中添加两列“ A”和“ B” df1,则可以pd.eval使用以下表达式进行调用

使用df.eval,只需提供列名称

因为在的上下文中df1,很明显“ A”和“ B”是指列名。

你还可以使用引用索引和列index(除非命名索引,否则将使用名称)。

或者,更一般地,对于具有1或更多级的索引数据帧的任何,可以参考第k 个使用变量索引的水平在表达“ilevel_k”表示“ 我 ndex在等级k ”。IOW,上面的表达式可以写成df1.eval("A + ilevel_0")

这些规则也适用于query

在本地/全局命名空间中访问变量 表达式内提供的变量必须以“ @”符号开头,以避免与列名混淆。

同样的道理query。

不用说,你的列名必须遵循python中有效标识符命名的规则,以便在内部访问eval。有关命名标识符的规则列表,请参见此处。

一个鲜为人知的事实是eval支持处理分配的多行表达式。例如,要基于某些列上的某些算术运算在df1中创建两个新列“ E”和“ F”,并基于先前创建的“ E”和“ F”来创建第三列“ G”,我们可以

真漂亮 但是,请注意,此功能不受支持query

它有助于将df.query其pd.eval视为用作子例程的函数

通常,query(顾名思义)用于评估条件表达式(即产生True / False值的表达式)并返回与True结果相对应的行。然后将表达式的结果传递给loc(在大多数情况下)以返回满足表达式的行。根据文档,

该表达式的求值结果首先传递给 DataFrame.loc,如果由于多维键(例如,DataFrame)而失败,则结果将传递给 DataFrame.__getitem__()

方法使用顶级pandas.eval()函数评估传递的查询

在相似的条件,query并df.eval在他们如何访问列名和变量都一样。

如上所述,两者之间的主要区别在于它们如何处理表达式结果。当你实际上通过这两个函数运行表达式时,这一点变得显而易见。例如,考虑

获取其中所有“ A”> =“ B”的行df1,我们将使用eval以下代码

m表示通过评估表达式“ A> = B”生成的中间结果。然后,我们使用蒙版进行过滤df1

但是,使用query,中间结果“ m”直接传递给loc,因此使用query,你只需要执行

性能方面,它是完全相同的。

但是后者更为简洁,并且只需一步即可表达相同的操作。

请注意,你也可以query像这样做一些奇怪的事情(例如,返回由df1.index索引的所有行)

但是不要。

底线:query在基于条件表达式查询或过滤行时,请使用。

python 2022/1/1 18:22:27 有715人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶