2013-07-09 7 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. Я был бы очень признателен, если бы у кого-то были идеи о том, как его векторизовать или ускорить. Я попытался заменить «.ix [inum, sym]» на «[sym] [inum]», но это еще медленнее.

  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 

EDIT:

Я просто перезапустил некоторый старый код, который использовал аналогичный цикл через панд DataFrame, чтобы установить значение. Раньше он занимал, возможно, 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 7-9-13 1:23 вечера:

я нашел временное решение! Я изменил код на ниже. По существу конвертировали каждый столбец в ndarray, а затем собрали новый столбец в списке python, прежде чем вставлять обратно в столбец в новом pandas DataFrame. Чтобы сделать 50 столбцов около 2000 строк, используя старую версию выше, заняло 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 - это dataframe, состоящий из 1s или 0s. 1 означает покупку или хранение ценной бумаги. 0 означает продажу или остаток денежных средств. Shortp состоит из -1 или 0. -1 продается коротким или остается коротким. 0 идет на денежные средства или остается наличными. Эта функция состоит в объединении длинной и короткой позиций в один сигнал, где 1 означает покупку или удержание, 0,5 означает выход из позиции покупки или остальное наличными, -1 означает короткий или короткий, а -0,5 означает выход из короткого или оставшегося купюрами. – geronimo

+0

Я добавил несколько примеров данных и желаемых результатов. Пожалуйста, дайте мне знать, если потребуется дополнительное разъяснение. – geronimo

ответ

0

Я считаю, что реализация была изменена в 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

Смежные вопросы