2013-07-09 77 views
0

我知道矢量化函数是编写速度代码的首选方法,但我无法想出一个方法来做这个函数没有循环的方法。我写这个函数的方式导致了非常缓慢的完成时间。 (传递两个dataframes与100列和2000行作为参数,该功能需要100秒的时间完成。我希望更多的像1秒。)有没有办法加快这个熊猫的功能?

def gen_fuzz_logic_signal(longp, shortp): 
    # Input dataframes should have 0, -1, or 1 value 
    flogic_signal = pd.DataFrame(index = longp.index, columns = longp.columns) 
    for sym in longp.columns: 
     print sym 
     prev_enter = 0 
     for inum in range(0, len(longp.index)): 
      cur_val = np.nan 
      if longp.ix[inum, sym] == 0 and prev_enter == +1: 
       cur_val = 0.5 
      if shortp.ix[inum, sym] == 0 and prev_enter == -1: 
       cur_val = -0.5 
      if longp.ix[inum, sym] == 1 and shortp.ix[inum, sym] == -1: 
       if longp.ix[inum - 1, sym] != 1: 
        cur_val = 1 
        prev_enter = 1 
       elif shortp.ix[inum - 1, sym] != -1: 
        cur_val = -1 
        prev_enter = -1 
       else: 
        cur_val = prev_enter 
      else: 
       if longp.ix[inum, sym] == 1: 
        cur_val = 1 
        prev_enter = 1 
       if shortp.ix[inum, sym] == -1: 
        cur_val = -1 
        prev_enter = -1 
      flogic_signal.ix[inum, sym] = cur_val 
    return flogic_signal 

给函数的输入是根本就是两个dataframes用的值无论是1,-1还是0.我真的很感激,如果有人有想法如何矢量化或加速。我尝试用“[sym] [inum]”替换“.ix [inum,sym]”,但速度更慢。

  GOOG longp GOOG shortp GOOG func result 
2011-07-28   0   -1    -1 
2011-07-29   0   -1    -1 
2011-08-01   0   -1    -1 
2011-08-02   0   -1    -1 
2011-08-03   0   -1    -1 
2011-08-04   0   -1    -1 
2011-08-05   0   -1    -1 
2011-08-08   0   0    -0.5 
2011-08-09   0   0    -0.5 
2011-08-10   0   0    -0.5 
2011-08-11   0   0    -0.5 
2011-08-12   1   0    1 
2011-08-15   1   0    1 
2011-08-16   1   0    1 
2011-08-17   1   0    1 
2011-08-18   1   0    1 
2011-08-19   1   0    1 
2011-08-22   1   0    1 
2011-08-23   1   0    1 
2011-08-24   1   0    1 
2011-08-25   1   0    1 
2011-08-26   1   0    1 
2011-08-29   1   0    1 
2011-08-30   1   0    1 
2011-08-31   1   0    1 
2011-09-01   1   0    1 
2011-09-02   1   0    1 
2011-09-06   1   0    1 
2011-09-07   1   0    1 
2011-09-08   1   0    1 
2011-09-09   1   0    1 
2011-09-12   1   0    1 
2011-09-13   1   0    1 
2011-09-14   1   0    1 
2011-09-15   1   0    1 
2011-09-16   1   0    1 
2011-09-19   1   0    1 
2011-09-20   1   0    1 
2011-09-21   1   0    1 
2011-09-22   1   0    1 
2011-09-23   1   0    1 
2011-09-26   1   0    1 
2011-09-27   1   0    1 
2011-09-28   1   0    1 
2011-09-29   0   0    0.5 
2011-09-30   0   -1    -1 
2011-10-03   0   -1    -1 
2011-10-04   0   -1    -1 
2011-10-05   0   -1    -1 
2011-10-06   0   -1    -1 
2011-10-07   0   -1    -1 
2011-10-10   0   -1    -1 
2011-10-11   0   -1    -1 
2011-10-12   0   -1    -1 
2011-10-13   0   -1    -1 
2011-10-14   0   -1    -1 
2011-10-17   0   -1    -1 
2011-10-18   0   -1    -1 
2011-10-19   0   -1    -1 
2011-10-20   0   -1    -1 


      IBM longp IBM shortp IBM func result 
2012-05-01   1   -1    1 
2012-05-02   1   -1    1 
2012-05-03   1   -1    1 
2012-05-04   1   -1    1 
2012-05-07   1   -1    1 
2012-05-08   1   0    1 
2012-05-09   1   0    1 
2012-05-10   1   0    1 
2012-05-11   1   0    1 
2012-05-14   1   0    1 
2012-05-15   1   0    1 
2012-05-16   0   -1    -1 
2012-05-17   0   -1    -1 
2012-05-18   0   -1    -1 
2012-05-21   0   -1    -1 
2012-05-22   0   -1    -1 
2012-05-23   0   -1    -1 
2012-05-24   0   -1    -1 
2012-05-25   0   -1    -1 
2012-05-29   0   -1    -1 
2012-05-30   0   -1    -1 
2012-05-31   0   -1    -1 
2012-06-01   0   -1    -1 
2012-06-04   0   -1    -1 
2012-06-05   0   -1    -1 
2012-06-06   0   -1    -1 
2012-06-07   0   -1    -1 
2012-06-08   1   -1    1 
2012-06-11   1   -1    1 
2012-06-12   1   -1    1 
2012-06-13   1   -1    1 
2012-06-14   1   -1    1 
2012-06-15   1   -1    1 
2012-06-18   1   -1    1 
2012-06-19   1   -1    1 
2012-06-20   1   -1    1 
2012-06-21   1   0    1 
2012-06-22   1   0    1 
2012-06-25   1   0    1 
2012-06-26   1   0    1 
2012-06-27   1   0    1 
2012-06-28   1   0    1 
2012-06-29   1   0    1 

编辑:

我只是重新运行所用类似的循环通过熊猫据帧设定值有一些旧的代码。它过去大概需要5秒钟,现在我发现它可能是100倍。我想知道这个问题是否是由于熊猫更新版本中发生了变化。这是我能想到的唯一变化。请参阅下面的代码。这需要73秒钟使用Pandas 0.11在我的电脑上运行。这对于一个非常基本的功能来说似乎非常缓慢,尽管它是按照元素操作的,但仍然如此。如果有人有机会,我会好奇下面多久你的电脑和你的熊猫版本。

import time 
import numpy as np 
import pandas as pd 
def timef(func, *args): 
    start= time.clock() 
    for i in range(2): 
     func(*args) 
    end= time.clock() 
    time_complete = (end-start)/float(2) 
    print time_complete 

def tfunc(num_row, num_col): 
    df = pd.DataFrame(index = np.arange(1,num_row), columns = np.arange(1,num_col)) 
    for col in df.columns: 
     for inum in range(1, len(df.index)): 
      df.ix[inum, col] = 0 #np.nan 
    return df 

timef(tfunc, 1000, 1000) <<< This takes 73 seconds on a Core i5 M460 2.53gz Windows 7 laptop. 

EDIT 2 13年7月9日下午1:23:

我找到了一个临时的解决方案!我将代码更改为下面的代码。基本上将每列转换为一个ndarray,然后将新列组装到一个python列表中,然后再插入到新的pandas DataFrame中的列中。使用上面的旧版本做约2000行的50列需要101秒。以下版本只需要0.19秒!现在对我来说足够快了。不知道为什么.ix太慢了。就像我上面所说的,在较早版本的熊猫中,我认为元素操作要快得多。

def gen_fuzz_logic_signal3(longp, shortp): 
    # Input dataframes should have 0 or 1 value 
    flogic_signal = pd.DataFrame(index = longp.index, columns = longp.columns) 
    for sym in longp.columns: 
     coll = longp[sym].values 
     cols = shortp[sym].values 
     prev_enter = 0 
     newcol = [None] * len(coll) 
     for inum in range(1, len(coll)): 
      cur_val = np.nan 
      if coll[inum] == 0 and prev_enter == +1: 
       cur_val = 0.5 
      if cols[inum] == 0 and prev_enter == -1: 
       cur_val = -0.5 
      if coll[inum] == 1 and cols[inum] == -1: 
       if coll[inum -1] != 1: 
        cur_val = 1 
        prev_enter = 1 
       elif cols[inum-1] != -1: 
        cur_val = -1 
        prev_enter = -1 
       else: 
        cur_val = prev_enter 
      else: 
       if coll[inum] == 1: 
        cur_val = 1 
        prev_enter = 1 
       if cols[inum] == -1: 
        cur_val = -1 
        prev_enter = -1 
      newcol[inum] = cur_val 
     flogic_signal[sym] = newcol 
    return flogic_signal 
+6

灿你解释了函数的目标,而不是让读者通过阅读代码来解决它? – BrenBarn

+0

这是一个财务数据问题。 Longp是由1或0组成的数据帧。 1表示购买或持有证券。 0意味着出售或保留现金。短缺由-1或0组成。-1卖空或者维持卖空。 0是现金或保留现金。这个功能是将多头头寸和空头头寸组合成一个信号,其中1代表买入或持有,0.5代表退出买入头寸或保持现金,-1代表空头或保持空头,-0.5代表退出空头或保持空头用现金。 – geronimo

+0

我添加了一些示例数据和期望的结果。请让我知道是否需要额外澄清。 – geronimo

回答

0

我相信.ix的实现确实在0.11变化。 (http://pandas.pydata.org/pandas-docs/stable/whatsnew.html)不确定是否与其相关。

一个快速的加速比我在0.10.1得到的是当我改变tfunc以下缓存列/系列更新

def tfunc(num_row, num_col): 
    df = pd.DataFrame(index = np.arange(1,num_row), columns = np.arange(1,num_col)) 
    for col in df.columns: 
     sdf = df[col] 
     for inum in range(1, len(df.index)): 
      sdf.ix[inum] = 0 #np.nan 
    return df 

它从〜80到〜9跑到我的机器上

+0

这个函数做了一些其他的事情:'pd.DataFrame(0,index = np.arange(1,num_row),columns = np。arange(1,num_col),dtype ='float')'除了有最后一行NaN吗? –

+0

我相信这是一个模拟原始循环的测试函数 – user1827356

相关问题