我有几十个条件(例如,foo > bar
),我需要对DataFrame
的~1MM行进行计算,最简洁的编写方法是将这些条件存储为字符串列表,并创建一个DataFrame
布尔结果(每个记录一行x每个条件一列)。(正在评估的用户输入是而不是。)
在寻求过早优化的过程中,我试图确定我是应该在DataFrame
(例如,df.eval("foo > bar")
)内编写这些条件进行求值,还是像eval("df.foo > df.bar")
那样将其留给python
根据documentation on enhancing eval performance:
You should not use eval() for simple expressions or for expressions involving small DataFrames. In fact, eval() is many orders of magnitude slower for smaller expressions/objects than plain ol’ Python. A good rule of thumb is to only use eval() when you have a DataFrame with more than 10,000 rows.
能够使用df.eval("foo > bar")
语法将是一件好事,因为我的列表将更具可读性,但我从来没有找到一个案例,它的评估速度不慢。文档显示了一些例子,其中pandas.eval()
比python eval()
(这与我的经验相符)快,但是DataFrame.eval()
(被列为“实验性的”)没有。在
例如,DataFrame.eval()
在一个大的ish DataFrame
上的一个不简单的表达式中仍然是一个明显的失败者:
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()
不支持完整的操作集。)
的source code数据帧.eval()显示它实际上只是创建要传递给的参数pd.评估():
其中,\u eval()只是的别名pd.评估()在模块开头导入:
^{pr2}$所以你可以用}一样好,但写起来更方便。在
df.eval()
做任何事情,你都可以用pd.eval()
+几行额外的行来设置。从目前的情况来看,df.eval()
永远不会比pd.eval()
快。但这并不意味着df.eval()
和{但是,在玩了
%prun
魔术之后,df.eval()
对df._get_index_resolvers()
的调用给df.eval()
方法增加了相当多的时间。最终,_get_index_resolvers()
最后调用了.copy()
的.copy()
方法,这是最终减慢速度的原因。同时,pd.eval()
在某个时候确实调用了numpy.ndarray.copy()
,但它花费的时间微不足道(至少在我的机器上)。在长话短说,
df.eval()
似乎比pd.eval()
慢,因为在引擎盖下,它只是pd.eval()
加上额外的步骤,这些步骤是非常重要的。在相关问题 更多 >
编程相关推荐