如何加快 Pandas 多级数据帧总和?

2024-01-07

我正在尝试加快几个大型多级数据帧的求和速度。

这是一个示例:

df1 = mul_df(5000,30,400) # mul_df to create a big multilevel dataframe
#let df2, df3, df4 = df1, df1, df1 to minimize the memory usage, 
#they can also be mul_df(5000,30,400) 
df2, df3, df4 = df1, df1, df1

In [12]: timeit df1+df2+df3+df4
1 loops, best of 3: 993 ms per loop

我对 993ms 不满意,有什么办法可以加快速度吗? cython 可以提高性能吗?如果是,如何编写 cython 代码?谢谢。

Note: mul_df()是创建演示多级数据帧的函数。

import itertools
import numpy as np
import pandas as pd

def mul_df(level1_rownum, level2_rownum, col_num, data_ty='float32'):
    ''' create multilevel dataframe, for example: mul_df(4,2,6)'''

    index_name = ['STK_ID','RPT_Date']
    col_name = ['COL'+str(x).zfill(3) for x in range(col_num)]

    first_level_dt = [['A'+str(x).zfill(4)]*level2_rownum for x in range(level1_rownum)]
    first_level_dt = list(itertools.chain(*first_level_dt)) #flatten the list
    second_level_dt = ['B'+str(x).zfill(3) for x in range(level2_rownum)]*level1_rownum

    dt = pd.DataFrame(np.random.randn(level1_rownum*level2_rownum, col_num), columns=col_name, dtype = data_ty)
    dt[index_name[0]] = first_level_dt
    dt[index_name[1]] = second_level_dt

    rst = dt.set_index(index_name, drop=True, inplace=False)
    return rst

Update:

我的奔腾双核的数据[电子邮件受保护] /cdn-cgi/l/email-protection、3.00GB RAM、WindowXP、Python 2.7.4、Numpy 1.7.1、Pandas 0.11.0、numexpr 2.0.1(Anaconda 1.5.0(32 位))

In [1]: from pandas.core import expressions as expr
In [2]: import numexpr as ne

In [3]: df1 = mul_df(5000,30,400)
In [4]: df2, df3, df4 = df1, df1, df1

In [5]: expr.set_use_numexpr(False)
In [6]: %timeit df1+df2+df3+df4
1 loops, best of 3: 1.06 s per loop

In [7]: expr.set_use_numexpr(True)
In [8]: %timeit df1+df2+df3+df4
1 loops, best of 3: 986 ms per loop

In [9]: %timeit  DataFrame(ne.evaluate('df1+df2+df3+df4'),columns=df1.columns,index=df1.index,dtype='float32')
1 loops, best of 3: 388 ms per loop

方法1:在我的机器上还不错(用numexpr禁用)

In [41]: from pandas.core import expressions as expr

In [42]: expr.set_use_numexpr(False)

In [43]: %timeit df1+df2+df3+df4
1 loops, best of 3: 349 ms per loop

方法二:使用numexpr(默认情况下启用,如果numexpr已安装)

In [44]: expr.set_use_numexpr(True)

In [45]: %timeit df1+df2+df3+df4
10 loops, best of 3: 173 ms per loop

方法三:直接使用numexpr

In [34]: import numexpr as ne

In [46]: %timeit  DataFrame(ne.evaluate('df1+df2+df3+df4'),columns=df1.columns,index=df1.index,dtype='float32')
10 loops, best of 3: 47.7 ms per loop

这些加速是通过使用实现的numexpr因为:

  • 避免使用中间临时数组(在您呈现的情况下可能是 在 numpy 中效率很低,我怀疑这是被评估的((df1+df2)+df3)+df4
  • 使用可用的多核

正如我上面暗示的,pandas 使用numexpr在某些类型的操作(0.11 中)的幕后,例如df1 + df2将以这种方式进行评估,但是您在此处给出的示例将导致多次调用numexpr(这是方法2比方法1更快。)。直接使用(方法3)ne.evaluate(...)实现更多的加速。

请注意,在pandas 0.13(0.12将于本周发布)中,我们实现了一个功能pd.eval这实际上将完全按照我上面的示例所做的事情。请继续关注(如果您喜欢冒险,这很快就会成为大师:https://github.com/pydata/pandas/pull/4037 https://github.com/pydata/pandas/pull/4037)

In [5]: %timeit pd.eval('df1+df2+df3+df4')
10 loops, best of 3: 50.9 ms per loop

最后回答一下你的问题,cython在这里根本没有帮助;numexpr对于此类问题非常有效(也就是说,有arecython 有帮助的情况)

需要注意的是:为了使用直接 Numexpr 方法,帧应该已经对齐(Numexpr 对 numpy 数组进行操作,并且不知道有关索引的任何信息)。它们也应该是单一的数据类型

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何加快 Pandas 多级数据帧总和? 的相关文章

随机推荐