小编典典

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

设置

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

np.random.seed(0)

df1 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD'))

df2 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD'))

df3 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD'))

df4 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD'))

pandas.eval -《失踪手册》

注意

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

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

x = 5

pd.eval("df1.A + (df1.B * x)")

这里要注意一些事情:

整个表达式是一个字符串

df1,df2和x引用全局命名空间中的变量,这些变量是eval在解析表达式时通过选择的

使用属性访问器索引访问特定的列。你也可以使用"df1['A'] + (df1['B'] * x)"达到相同的效果。

我将在解释以下target=...属性的部分中讨论重新分配的特定问题。但是现在,这是使用以下命令进行有效操作的更简单示例pd.eval:

pd.eval("df1.A + df2.A") # Valid, returns a pd.Series object

pd.eval("abs(df1) ** .5") # Valid, returns a pd.DataFrame object

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

pd.eval("df1 > df2")

pd.eval("df1 > 5")

pd.eval("df1 < df2 and df3 < df4")

pd.eval("df1 in [1, 2, 3]")

pd.eval("1 < 2 < 3")

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

除左移(<>)运算符外的算术运算,例如df + 2 * pi / s ** 4 % 42-the_golden_ratio

比较操作,包括链式比较,例如 2 < df < df2

布尔运算(例如df < df2 and df3 < df4或)not df_bool list和tuple文字(例如[1, 2]或)(1, 2)

属性访问,例如 df.a

下标表达式,例如 df[0]

简单的变量求值,例如,pd.eval('df')(这不是很有用)

数学函数:sin,cos,exp,log,expm1,log1p,sqrt,sinh,cosh,tanh,arcsin,arccos,arctan,arcosh,arcsinh,arctanh,abs和arctan2。

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

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

pd.eval('df1.A * (df1.index > 1)')

解析器选择:parser=…参数

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

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

pd.eval("(df1 > df2) & (df3 < df4)")

将与

pd.eval("df1 > df2 & df3 < df4")

# pd.eval("df1 > df2 & df3 < df4", parser='pandas')

而且也一样

pd.eval("df1 > df2 and df3 < df4")

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

(df1 > df2) & (df3 < df4)

没有那个,我们最终会

df1 > df2 & df3 < df4

ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

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

pd.eval("(df1 > df2) & (df3 < df4)", parser='python')

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

pd.eval("df1 == [1, 2, 3]")

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

pd.eval("df1 in [1, 2, 3]")

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

后端选择:engine=…参数

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

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

df = pd.DataFrame({'A': ['abc', 'def', 'abacus']})

pd.eval('df.A.str.contains("ab")', engine='python')

0 True

1 False

2 True

Name: A, dtype: bool

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

local_dict和global_dict论点

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

例如,

pd.eval("df1 > thresh")

UndefinedVariableError: name 'thresh' is not defined

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

pd.eval("df1 > thresh", local_dict={'thresh': 10})

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

mydict = {'thresh': 5}

# Dictionary values with *string* keys cannot be accessed without

# using the 'python' engine.

pd.eval('df1 > mydict["thresh"]', engine='python')

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

target(+ inplace)参数,并赋值表达式

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

考虑问题中的例子

x = 5

df2['D'] = df1['A'] + (df1['B'] * x)

要将列“ D”分配给df2,

pd.eval('D = df1.A + (df1.B * x)', target=df2)

A B C D

0 5 9 8 5

1 4 3 0 52

2 5 0 2 22

3 8 1 3 48

4 3 7 0 42

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

pd.eval('df1.A + df2.A')

0 10

1 11

2 7

3 16

4 10

dtype: int32

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

df = pd.DataFrame(columns=list('FBGH'), index=df1.index)

df

F B G H

0 NaN NaN NaN NaN

1 NaN NaN NaN NaN

2 NaN NaN NaN NaN

3 NaN NaN NaN NaN

4 NaN NaN NaN NaN

df = pd.eval('B = df1.A + df2.A', target=df)

# Similar to

# df = df.assign(B=pd.eval('df1.A + df2.A'))

df

F B G H

0 NaN 10 NaN NaN

1 NaN 11 NaN NaN

2 NaN 7 NaN NaN

3 NaN 16 NaN NaN

4 NaN 10 NaN NaN

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

pd.eval('B = df1.A + df2.A', target=df, inplace=True)

# Similar to

# df['B'] = pd.eval('df1.A + df2.A')

df

F B G H

0 NaN 10 NaN NaN

1 NaN 11 NaN NaN

2 NaN 7 NaN NaN

3 NaN 16 NaN NaN

4 NaN 10 NaN NaN

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

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

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

df = df.eval("B = @df1.A + @df2.A")

# df.eval("B = @df1.A + @df2.A", inplace=True)

df

F B G H

0 NaN 10 NaN NaN

1 NaN 11 NaN NaN

2 NaN 7 NaN NaN

3 NaN 16 NaN NaN

4 NaN 10 NaN NaN

注意的

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

pd.eval("[1, 2, 3]")

array([1, 2, 3], dtype=object)

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

pd.eval("[[1, 2, 3], [4, 5], [10]]", engine='python')

[[1, 2, 3], [4, 5], [10]]

以及字符串列表:

pd.eval(["[1, 2, 3]", "[4, 5]", "[10]"], engine='python')

[[1, 2, 3], [4, 5], [10]]

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

pd.eval(["[1]"] * 100, engine='python') # Works

pd.eval(["[1]"] * 101, engine='python')

AttributeError: 'PandasExprVisitor' object has no attribute 'visit_Ellipsis'

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

DataFrame.eval -与并置 pandas.eval

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

def eval(self, expr, inplace=False, **kwargs):

from pandas.core.computation.eval import eval as _eval

inplace = validate_bool_kwarg(inplace, 'inplace')

resolvers = kwargs.pop('resolvers', None)

kwargs['level'] = kwargs.pop('level', 0) + 1

if resolvers is None:

index_resolvers = self._get_index_resolvers()

resolvers = dict(self.iteritems()), index_resolvers

if 'target' not in kwargs:

kwargs['target'] = self

kwargs['resolvers'] = kwargs.get('resolvers', ()) + tuple(resolvers)

return _eval(expr, inplace=inplace, **kwargs)

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使用以下表达式进行调用:

pd.eval("df1.A + df1.B")

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

df1.eval("A + B")

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

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

df1.eval("A + index")

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

这些规则也适用于query。

在本地/全局命名空间中访问变量

表达式内提供的变量必须以“ @”符号开头,以避免与列名混淆。

A = 5

df1.eval("A > @A")

同样的道理query。

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

多行查询和分配

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

df1.eval("""

E = A + B

F = @df2.A + @df2.B

G = E >= F

""")

A B C D E F G

0 5 0 3 3 5 14 False

1 7 9 3 5 16 7 True

2 2 4 7 6 6 5 True

3 8 8 1 6 16 9 True

4 7 7 8 1 14 10 True

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

evalv / s- query最终词

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

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

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

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

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

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

df1.A

0 5

1 7

2 2

3 8

4 7

Name: A, dtype: int32

df1.B

0 9

1 3

2 0

3 1

4 7

Name: B, dtype: int32

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

m = df1.eval("A >= B")

m

0 True

1 False

2 False

3 True

4 True

dtype: bool

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

df1[m]

# df1.loc[m]

A B C D

0 5 0 3 3

3 8 8 1 6

4 7 7 8 1

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

df1.query("A >= B")

A B C D

0 5 0 3 3

3 8 8 1 6

4 7 7 8 1

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

df1_big = pd.concat([df1] * 100000, ignore_index=True)

%timeit df1_big[df1_big.eval("A >= B")]

%timeit df1_big.query("A >= B")

14.7 ms ± 33.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

14.7 ms ± 24.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

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

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

df1.query("index")

# Same as df1.loc[df1.index] # Pointless,... I know

A B C D

0 5 0 3 3

1 7 9 3 5

2 2 4 7 6

3 8 8 1 6

4 7 7 8 1

但是不要。

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

2020-02-17

python中错误useofeval_Python-使用pd.eval()在熊猫中进行动态表达评估相关推荐

  1. python按列名删除某列_python-根据熊猫中的列名删除多个列

    python-根据熊猫中的列名删除多个列 我有一些数据,导入时会得到以下不需要的列,我正在寻找一种删除所有这些数据的简便方法 'Unnamed: 24', 'Unnamed: 25', 'Unname ...

  2. c语言中错误为ffblk未定义,C语言中头文件及函数的含意的总分类

    ALLOC.H 说明内存管理函数(分配.释放等). ASSERT.H 定义assert调试宏. BIOS.H 说明调用IBM-PC ROM BIOS子程序的各个函数. CONIO.H 说明调用DOS控 ...

  3. python创建csv文件并写入-【已解决】Python中创建和保存数据到csv文件中

    此处希望在python中,将A和B的QA对话,中错误的对话,保存到csv中. 打算自己先创建一个csv文件,然后后续每个对话出错的话,就append追加写入到csv中. 其中希望用逗号分隔.而句子中如 ...

  4. python的错误处理

    一.python的错误处理在程序运行的过程中,如果发生了错误,可以事先约定返回一个错误代码,这样,就可以知道是否有错以及出错的原因. 在操作系统提供的调用中,返回错误码非常常见.比如打开文件的函数op ...

  5. 关于python字符编码以下选项中错误的是_关于Python文件打开模式的描述,以下选项中错误的是...

    [单选题]下列Python保留字中,不用于表示分支结构的是 [单选题]下列哪项不是python中文件的读取操作 [单选题]以下程序的输出结果是: s='' ls = [1,2,3,4] for l i ...

  6. 关于python字符编码以下选项中错误的是_关于 Python 字符编码,以下选项中描述错误的是...

    [单选题]下面代码的输出结果是: a = 20 b = a | 3 a &= 7 print(b ,end=",") print(a) [单选题]Python 3.x 版本 ...

  7. 以下关于python二维数据的描述中错误的是_python第二章1

    1. (单选题) Python 3.x 版本的保留字总数是( ) A.27B.29C.33D.62. (单选题) 以下选项中,不是 Python 语言保留字的是( ) A.whileB.passC.d ...

  8. python中的float和eval_python中eval和float_python中eval与json.loads对json的处理

    JSON有两种结构: "名称/值"对的集合(A collection of name/value pairs).不同的语言中,它被理解为对象(object),纪录(record), ...

  9. python中if错误-Python中错误和异常

    第1章 概念 错误 语法错误:代码不符合解释器或编译器的语法 逻辑错误:不完整或不合法的输入或者计算出现问题 异常:代码执行过程中,出现问题导致程序无法执行 程序遇到逻辑或算法问题 运行过程中计算机错 ...

最新文章

  1. 轻松抓鸡蛋、剪纸、夹芯片,这只“机械爪”堪比人手!
  2. ssh linux免密登录。。。。生产共钥到另一台主机
  3. android-仿QQtab
  4. Android ExecutorService 的理解与使用
  5. 体验paddle2.0rc版本API-Model--实现Mnist数据集模型训练
  6. 镜头视场角计算工具_再谈远心镜头的设计及其独特的性能
  7. 用Markdown写博客快速入门
  8. ibdata1 mysql_ibdata1 mysql-bin
  9. bzoj 4318 OSU!
  10. 淘宝运营之:店铺信用分计算规则
  11. win7添加一个计算机图标,Win7系统任务栏添加计算机图标的步骤图解
  12. AHRS和IMU的联系和区别
  13. 51单片机学习笔记——STC15W201S系列
  14. 22款奔驰S400L升级原厂主动氛围灯,H17钢琴条纹饰板等,浪漫奢华
  15. 脂肪烃树脂行业调研报告 - 市场现状分析与发展前景预测
  16. Flink的批流统一:Ⅱ
  17. Word2019建立自己的模板
  18. 双向长短期记忆网络模型_一种基于双向长短期记忆网络的定位修正方法与流程...
  19. BI大数据的星形模型和雪花模型
  20. Mr.Alright---Android 11 mtk平台,桌面google日历名称不跟随系统语言变化

热门文章

  1. 河北传媒学院计算机大四,2020年6月河北传媒学院英语四级报名条件有哪些
  2. 百度浏览器奔跑的小熊
  3. 项目中应该如何提升java接口的响应速度
  4. 能vivado仿真却不能DC综合的错误
  5. 新概念75课摘要写作(二)
  6. Epson Pos Printer for .net
  7. 基于springboot+h5+websocket的即时通讯客服系统和百度实时语音转译(语音在线识别)
  8. 对一个排序去重。要求:有重复的关键字,保留后一个,删除前面的
  9. android sdk教学,Android SDK开发
  10. Integer类----装箱