当前位置: 首页 > 知识库问答 >
问题:

何时使用DataFrame.eval()与pandas.eval()或Python eval()比较

阎咏思
2023-03-14

我有几十个条件(例如,foo

为了寻求过早的优化,我试图确定是否应该在DataFrame(例如,df.eval("foo

根据关于增强评估性能的文件:

对于简单表达式或涉及小数据帧的表达式,不应使用eval()。事实上,对于较小的表达式/对象,eval()比普通的ol'Python慢很多数量级。一个很好的经验法则是,只有当数据帧的行数超过10000行时,才使用eval()。

如果能够使用df.eval(“foo

例如,DataFrame.eval()在大型ishDataFrame上的一个不简单表达式中仍然是一个明显的输家:

import pandas as pd
import numpy as np
import numexpr
import timeit

someDf = pd.DataFrame({'a':np.random.uniform(size=int(1e6)), 'b':np.random.uniform(size=int(1e6))})

%timeit -n100 someDf.eval("a**b - a*b > b**a - b/a") # DataFrame.eval() on notional expression
%timeit -n100 eval("someDf['a']**someDf['b'] - someDf['a']*someDf['b'] > someDf['b']**someDf['a'] - someDf['b']/someDf['a']")
%timeit -n100 pd.eval("someDf.a**someDf.b - someDf.a*someDf.b > someDf.b**someDf.a - someDf.b/someDf.a")

100 loops, best of 3: 29.9 ms per loop
100 loops, best of 3: 18.7 ms per loop
100 loops, best of 3: 15.4 ms per loop

因此,DataFrame.eval()的好处仅仅是简化输入,还是我们可以确定使用此方法的情况实际上更快?

对于何时使用哪个eval(),是否有其他指导原则?(我知道pandas.eval()不支持完整的操作集。)

pd.show_versions()

INSTALLED VERSIONS
------------------
commit: None
python: 3.5.1.final.0
python-bits: 64
OS: Windows
OS-release: 7
machine: AMD64
processor: Intel64 Family 6 Model 63 Stepping 2, GenuineIntel
byteorder: little
LC_ALL: None
LANG: en_US

pandas: 0.18.0
nose: 1.3.7
pip: 8.1.2
setuptools: 20.3
Cython: 0.23.4
numpy: 1.10.4
scipy: 0.17.0
statsmodels: None
xarray: None
IPython: 4.1.2
sphinx: 1.3.1
patsy: 0.4.0
dateutil: 2.5.3
pytz: 2016.2
blosc: None
bottleneck: 1.0.0
tables: 3.2.2
numexpr: 2.5
matplotlib: 1.5.1
openpyxl: 2.3.2
xlrd: 0.9.4
xlwt: 1.0.0
xlsxwriter: 0.8.4
lxml: 3.6.0
bs4: 4.4.1
html5lib: None
httplib2: None
apiclient: None
sqlalchemy: 1.0.12
pymysql: None
psycopg2: None
jinja2: 2.8
boto: 2.39.0

共有1个答案

全彬
2023-03-14

那么,DataFrame.eval()的好处仅仅是简化了输入,还是我们可以确定使用此方法的情况实际上更快?

DataFrame.eval()的源代码显示它实际上只是创建要传递给pd.eval()的参数:

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

    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()的别名:

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

因此,您可以使用df.eval()执行任何操作,也可以使用pd.eval()执行一些额外的行来进行设置。就目前的情况来看,df.eval()从来没有严格地比pd.eval()快过。但这并不意味着在某些情况下,df.eval()pd.eval()一样好,但编写起来更方便。

然而,在使用了%prun魔法之后,似乎df.eval()df._get_index_resolvers()的调用为<--plhd--1/增加了相当多的时间>()方法。最终,_get_index_resolvers()调用了. Copp()方法numpy.ndarray,这最终会减慢速度。同时,pd.eval()确实在某个时候调用numpy.ndarray.copy(),但是它花费的时间可以忽略不计(至少在我的机器上)。

长话短说,似乎df.eval()往往比pd.eval()慢,因为在引擎盖下,它只是带有额外步骤的pd.eval()这些步骤都很重要。

 类似资料:
  • 问题内容: 我有一个需要在字段上排序的对象列表,例如“分数”。我不加思索地编写了一个实现Comparator的新类,该类可以完成任务并且可以工作。 现在回头看一下,我想知道是否应该让我的类实现Comparable,而不是创建一个实现Comparator的新类。分数是订购对象的唯一字段。 我做的可接受的做法是什么? 正确的方法是“首先让类实现Comparable(用于自然排序),如果需要替代字段比较

  • 我的程序实现了一个类,其对象包含以下实例变量:、、和。 在对链接列表执行任何其他操作之前,我需要对产品的链接列表进行排序。 我想先按优先级(从最低到最高)对列表进行排序。如果优先级相同,请查看价格(从低到高),然后查看名称(按字母顺序)。 我做了很多关于、和的阅读。我相信我需要使用接口并实现一个方法。我的想法是,因为、和都有一个“自然”排序,所以使用更有意义。 然后当我想对我的LinkedList

  • 问题内容: 我已经实现了一个图形。我想针对顶点 的度对给定的顶点子集进行排序。因此,我编写了一个名为的自定义比较器 . So, which one of the below is more efficient? Using Using 注意,第二种方法不是函数,而是单行代码。 凭直觉,我宁愿选择第二个。但是我不确定它是否更有效。 问题答案: Java API包含许多Collection和Map实现

  • 我正在使用一个独立的星火集群,一个主和两个工人。我真的不明白如何明智地使用SPARK_CLASSPATH或sparkcontext.addjar。我两个都试过了,看起来addJar并不像我以前认为的那样起作用。 在我的例子中,我尝试在闭包中或外部使用一些joda-time函数。如果我将SPARK_CLASSPATH设置为joda-time jar的路径,那么一切正常。但如果我删除SPARK_CLA

  • 我需要弄清楚一些事情。我一直在寻找这个问题的答案,但我似乎找不到一个好的答案来回答我的具体问题(例如,这个问题是对答案的蚕食:servlet和web服务之间的区别)。 据我所知,在“面向MVC”的web应用程序中,有不同的方法可以实现“请求处理”,也就是“控制器”,其中两种方法是: null null [编辑]:强调的关键词

  • 我是Java GUI编程新手,对何时使用哪些工具有几个问题。 当我的应用程序运行时,会出现一个JFrame,它使用内容面板显示用户3个按钮。我希望每个按钮都能显示不同的屏幕,但不能在单独的窗口中打开。为了实现这一点,我目前正在处理当前的JFrame,并用新内容创建一个新的JFrame。以下是我的问题。 > 我应该为每一次按钮点击创建一个新的JPanel,而不是创建一个新的JFrame吗?如果这个问