【发布时间】:2017-09-28 22:52:47
【问题描述】:
我有一个大约 200 万行的财务数据集。我想将其作为 pandas 数据框导入,并通过利用一些现有列值应用行函数来添加其他列。为此,我不想使用任何技术,如并行化、hadoop for python 等,因此我面临以下问题:
我已经在执行类似于下面示例的操作,但性能很差,大约 24 分钟才能通过大约 20K 行。 注意:这不是实际功能,它完全是虚构的。 对于其他列,我正在计算各种金融期权指标。我怀疑速度慢主要是由于迭代所有行,而不是函数本身,因为它们相当简单(例如计算期权的价格)。我知道我可以加快函数本身的一些小事情,例如使用 erf 而不是正态分布,但为此我想专注于整体问题本身。
def func(alpha, beta, time, vol):
px = (alpha*beta)/time * vol
return px
# Method 1 (could also use itertuples here) - this is the one that takes ~24 minutes now
for row in df.iterrows():
df['px'][row] = func(alpha, beta, df['time'][row], df['vol'][row])
我也尝试过对其进行矢量化,但不断收到有关“无法序列化浮点数”或类似内容的错误。
我的想法是尝试以下方法之一,但我不确定哪种方法理论上最快?是否存在与运行这些相关的非线性,例如 1000 行的测试不一定表明在所有 200 万行中哪一个是最快的? 可能是一个单独的问题,但我应该专注于更有效的管理方法数据集而不是仅仅专注于应用函数?
# Alternative 1 (df.apply with existing function above)
df['px'] = df.apply(lambda row: func(alpha, beta, row['time'], row['vol']), axis=1)
# Alternative 2 (numba & jit)
@jit
def func(alpha, beta, time, vol):
px = (alpha*beta)/time * vol
return px
# Alternative 3 (cython)
def func_cython(double alpha, double beta, double time, double vol):
cdef double px
px = (alpha*beta)/time * vol
return px
对于 Cython 和 numba,我是否仍会使用 df.apply 遍历所有行?还是有更有效的方法?
我参考了以下内容,发现它们有助于理解各种选项,但不是做到这一点的“最佳”方式(尽管我认为这最终取决于应用程序)。
https://lectures.quantecon.org/py/need_for_speed.html
Speeding up a numpy loop in python?
http://www.devx.com/opensource/improve-python-performance-with-cython.html
【问题讨论】:
-
“我也尝试过对其进行矢量化,但不断收到有关“无法序列化浮点数”或类似内容的错误。”是您应该解决的问题,以便您可以
df['px'] = func(alpha, beta, df['time'], df['vol'])。 -
您能否提供一个最小示例,以便我们可以重现“无法序列化浮点数”问题?这也可能会影响任何使用 numba 或 cython 的解决方案,因为它们需要正确的类型才能获得最佳执行速度。
-
是的,肯定会,但不会持续几个小时。谢谢!
标签: python performance pandas cython numba