Pandas 数据帧 - python 中的速度:数据帧操作、numba、cython
Pandas dataframe - speed in python: dataframe operations, numba, cython
我有一个大约有 200 万行的金融数据集。我想将其导入为 pandas 数据框,并通过应用一些现有列值的行向函数来添加其他列。为此,我不想使用任何技术,如并行化、python 的 hadoop 等,因此我面临以下问题:
我已经在执行类似于下面的示例,但性能很差,大约需要 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])
我也尝试过对其进行矢量化,但一直收到有关 'cannot serialize float' 或类似内容的错误。
我的想法是尝试以下方法之一,但我不确定理论上哪种方法最快?是否存在与 运行 这些相关联的非线性,以至于 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 遍历所有行?还是有更有效的方法?
我参考了以下内容,发现它们有助于理解各种选项,但不是 'best' 方法是什么(尽管我认为这最终取决于应用程序)。
https://lectures.quantecon.org/py/need_for_speed.html
Numpy vs Cython speed
Speeding up a numpy loop in python?
http://www.devx.com/opensource/improve-python-performance-with-cython.html
简单地说:
df.loc[:, 'px'] = (alpha * beta) / df.loc[:, 'time'] * df.loc[:, 'vol']
顺便说一下,您的 for-loop/lambda 解决方案很慢,因为每个 pandas 访问的开销很大。因此,分别访问每个单元格(通过遍历每一行)比访问整列要慢得多。
我有一个大约有 200 万行的金融数据集。我想将其导入为 pandas 数据框,并通过应用一些现有列值的行向函数来添加其他列。为此,我不想使用任何技术,如并行化、python 的 hadoop 等,因此我面临以下问题:
我已经在执行类似于下面的示例,但性能很差,大约需要 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])
我也尝试过对其进行矢量化,但一直收到有关 'cannot serialize float' 或类似内容的错误。
我的想法是尝试以下方法之一,但我不确定理论上哪种方法最快?是否存在与 运行 这些相关联的非线性,以至于 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 遍历所有行?还是有更有效的方法?
我参考了以下内容,发现它们有助于理解各种选项,但不是 'best' 方法是什么(尽管我认为这最终取决于应用程序)。
https://lectures.quantecon.org/py/need_for_speed.html
Numpy vs Cython speed
Speeding up a numpy loop in python?
http://www.devx.com/opensource/improve-python-performance-with-cython.html
简单地说:
df.loc[:, 'px'] = (alpha * beta) / df.loc[:, 'time'] * df.loc[:, 'vol']
顺便说一下,您的 for-loop/lambda 解决方案很慢,因为每个 pandas 访问的开销很大。因此,分别访问每个单元格(通过遍历每一行)比访问整列要慢得多。