【问题标题】:Pandas dataframe - speed in python: dataframe operations, numba, cythonPandas 数据帧 - python 中的速度:数据帧操作、numba、cython
【发布时间】: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

Numpy vs Cython speed

Speeding up a numpy loop in python?

Cython optimization

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


【解决方案1】:

简单地说:

df.loc[:, 'px'] = (alpha * beta) / df.loc[:, 'time'] * df.loc[:, 'vol']

顺便说一句,您的 for-loop/lambda 解决方案很慢,因为每个 pandas 访问的开销很大。所以单独访问每个单元格(通过循环遍历每一行)比访问整列要慢得多。

【讨论】:

  • 将单列访问写成df['px']等会稍微快一些/更惯用。
  • @chrisb 我更喜欢明确且一致地使用df.loc[row, col]。因为df[] 在设置值时可能会导致链式索引出现问题。
猜你喜欢
  • 2018-08-03
  • 2016-03-28
  • 2022-01-25
  • 2020-05-31
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 2018-02-01
  • 2018-12-04
相关资源
最近更新 更多