Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何加速多级数据帧和?_Python_Performance_Pandas_Cython - Fatal编程技术网

Python 如何加速多级数据帧和?

Python 如何加速多级数据帧和?,python,performance,pandas,cython,Python,Performance,Pandas,Cython,我正在尝试加快几个大型多级数据帧的求和速度 以下是一个示例: 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]: ti

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

以下是一个示例:

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代码?谢谢

注意
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
更新:

我的奔腾双核上的数据T4200@2.00GHZ,3.00GB内存,WindowXP,Python 2.7.4,Numpy 1.7.1,Pandas 0.11.0,numexpr 2.0.1(Anaconda 1.5.0(32位))


方法1:在我的机器上(禁用
numexpr

方法2:使用
numexpr
(如果安装了
numexpr
,则默认启用该方法)

方法3:直接使用
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在某些类型的ops(在0.11中)的引擎盖下使用
numexpr
,例如
df1+df2
将以这种方式进行评估,但是您在这里给出的示例将导致多次调用
numexpr
(这是方法2,比方法1快)。使用直接(方法3)
ne进行评估(…)
实现了更多的加速

请注意,在pandas 0.13(本周将发布0.12)中,我们实现了一个函数
pd.eval
,该函数实际上与我上面的示例完全相同。请继续关注(如果您有冒险精神,这将很快出现在master中:)

最后回答您的问题,
cython
在这里根本没有帮助;
numexpr
在这类问题上非常有效(也就是说,在某些情况下cython是有帮助的)


一个警告:为了使用直接Numexpr方法,帧应该已经对齐(Numexpr在numpy数组上运行,并且对索引一无所知)。此外,它们应该是单个数据类型。方法1:在我的机器上没有那么糟糕(禁用了
Numexpr

方法2:使用
numexpr
(如果安装了
numexpr
,则默认启用该方法)

方法3:直接使用
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在某些类型的ops(在0.11中)的引擎盖下使用
numexpr
,例如
df1+df2
将以这种方式进行评估,但是您在这里给出的示例将导致多次调用
numexpr
(这是方法2,比方法1快)。使用直接(方法3)
ne进行评估(…)
实现了更多的加速

请注意,在pandas 0.13(本周将发布0.12)中,我们实现了一个函数
pd.eval
,该函数实际上与我上面的示例完全相同。请继续关注(如果您有冒险精神,这将很快出现在master中:)

最后回答您的问题,
cython
在这里根本没有帮助;
numexpr
在这类问题上非常有效(也就是说,在某些情况下cython是有帮助的)

一个警告:为了使用直接Numexpr方法,帧应该已经对齐(Numexpr在numpy数组上运行,并且不知道任何索引)。此外,它们应该是单个数据类型

其他观察值
  • 如果你的机器上只有两个内核,你就不能期望有更多的加速。最终,numexpression依赖于并行化和cpu缓存的性能使用
  • 您所做的在某种程度上是错误的。数据帧上的Numexpressions是快速的,但却是错误的。如果数据帧的索引不相等,则它们不会返回正确的结果。不同的排序已经给您带来了麻烦,我将在下面介绍
  • 如果您添加了具有不同索引的数据帧,那么整个性能就不再那么好了。好吧,Pandas通过查找相应的索引项为您添加适当的行做了相当好的工作。这带来了自然成本
以下是我的意见: -首先,我复制您的测试用例并得出其他结果。在Pandas的引擎盖下使用numexpression可以显著提高性能。 -其次,我按降序对四个数据帧中的一个进行排序,然后重新运行所有案例。性能中断,此外,(如预期的那样)对Pandas数据帧的NumeExpression评估会导致错误的结果

所有帧上的索引相等 这个案例复制了您的案例。唯一的区别是,我创建了inital DataFrame实例的副本。因此没有共享内容。使用了不同的对象(ID)来确保numexpression可以处理它

导入itertools
将numpy作为np导入
作为pd进口熊猫
def mul_df(level1_rownum,level2_rownum,col_num,data_ty='float32'):
''创建多级数据帧,例如:mul_df(4,2,6)''
索引名称=['STK\U ID','RPT\U日期']
col_name=['col'+str(x).zfill(3)表示范围内的x(col_num)]
第一级\u dt=[[A'+str(x).zfill(4)]*范围内x的2级\u行数(1级\u行数)]
first_level_dt=list(itertools.chain(*first_level_dt))#展平列表
第二级\u dt=['B'+str(x).zfill(3)表示范围内的x(level2\u rownum)]*level1\u rownum
dt=pd.DataFrame(np.random.randn(level1_rownum*level2_rownum,col_num),columns=col_name,dtype=data_ty)
dt[索引名称[0]]=一级dt
dt[索引名称[1]]=第二级\u dt
rst=dt.set\U inde
In [44]: expr.set_use_numexpr(True)

In [45]: %timeit df1+df2+df3+df4
10 loops, best of 3: 173 ms per loop
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
In [5]: %timeit pd.eval('df1+df2+df3+df4')
10 loops, best of 3: 50.9 ms per loop
564 ms ± 10.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
152 ms ± 1.47 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
66.4 ms ± 1.16 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
True
1.36 s ± 67.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
928 ms ± 39.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
68 ms ± 2.2 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
False