使用pandas进行代码/循环优化

时间:2014-04-30 16:28:02

标签: python performance optimization pandas cython

我需要优化这个循环,需要2.5秒。需要的是我在脚本中称它超过3000次。 该代码的目的是创建两个在线性系统中使用的矩阵。

有人在Python或Cython中有任何想法吗?

 ## df is only here for illustration and date_indicatrice changes upon function call
 df     = pd.DataFrame(0, columns=range(6), 
                       index=pd.date_range(start = pd.datetime(2010,1,1),
                       end = pd.datetime(2020,1,1), freq="H"))
 mat    = pd.DataFrame(0,index=df.index,columns=range(6))
 mat_bp = pd.DataFrame(0,index=df.index,columns=range(6*2))

 date_indicatrice = [(pd.datetime(2010,1,1), pd.datetime(2010,4,1)),
                     (pd.datetime(2012,5,1), pd.datetime(2019,4,1)),
                     (pd.datetime(2013,4,1), pd.datetime(2019,4,1)),
                     (pd.datetime(2014,3,1), pd.datetime(2019,4,1)),
                     (pd.datetime(2015,1,1), pd.datetime(2015,4,1)),
                     (pd.datetime(2013,6,1), pd.datetime(2018,4,1))]

timer = time.time()

for j, (d1,d2) in enumerate(date_indicatrice):
    result      = df[(mat.index>=d1)&(mat.index<=d2)]
    result2     = df[(mat.index>=d1)&(mat.index<=d2)&(mat.index.hour>=8)]
    mat.loc[result.index,j]       = 1.
    mat_bp.loc[result2.index,j*2] = 1.
    mat_bp[j*2+1] = (1 - mat_bp[j*2]) * mat[j]

print time.time()-timer

1 个答案:

答案 0 :(得分:1)

你走了。我测试了以下内容,我在mat和mat_bp中得到了与原始代码相同的结果矩阵,但在我的机器上的原始代码的0.07秒和1.4秒之间。

真正的减速是由于使用了result.index和result2.index。按日期时间查找比使用索引查找要慢得多。我尽可能使用二进制搜索来找到正确的索引。

import pandas as pd
import numpy as np
import time
import bisect
## df is only here for illustration and date_indicatrice changes upon function call
df     = pd.DataFrame(0, columns=range(6),
                      index=pd.date_range(start = pd.datetime(2010,1,1),
                      end = pd.datetime(2020,1,1), freq="H"))
mat    = pd.DataFrame(0,index=df.index,columns=range(6))
mat_bp = pd.DataFrame(0,index=df.index,columns=range(6*2))

date_indicatrice = [(pd.datetime(2010,1,1), pd.datetime(2010,4,1)),
                    (pd.datetime(2012,5,1), pd.datetime(2019,4,1)),
                    (pd.datetime(2013,4,1), pd.datetime(2019,4,1)),
                    (pd.datetime(2014,3,1), pd.datetime(2019,4,1)),
                    (pd.datetime(2015,1,1), pd.datetime(2015,4,1)),
                    (pd.datetime(2013,6,1), pd.datetime(2018,4,1))]

timer = time.time()

for j, (d1,d2) in enumerate(date_indicatrice):
    ind_start = bisect.bisect_left(mat.index, d1)
    ind_end = bisect.bisect_right(mat.index, d2)
    inds = np.array(xrange(ind_start, ind_end))
    valid_inds = inds[mat.index[ind_start:ind_end].hour >= 8]
    mat.loc[ind_start:ind_end,j]       = 1.
    mat_bp.loc[valid_inds,j*2] = 1.
    mat_bp[j*2+1] = (1 - mat_bp[j*2]) * mat[j]

print time.time()-timer