Я знаю, что векторизованные функции являются предпочтительным способом написания кода для скорости, но я не могу понять, как это сделать, что делает эта функция без циклов. То, как я написал эту функцию, приводит к чрезвычайно медленному времени завершения. (Передача двух 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
Может вы объясняете цель функции вместо того, чтобы оставлять читателей, чтобы разобраться в этом, читая код? – BrenBarn
Это проблема финансовых данных. Longp - это dataframe, состоящий из 1s или 0s. 1 означает покупку или хранение ценной бумаги. 0 означает продажу или остаток денежных средств. Shortp состоит из -1 или 0. -1 продается коротким или остается коротким. 0 идет на денежные средства или остается наличными. Эта функция состоит в объединении длинной и короткой позиций в один сигнал, где 1 означает покупку или удержание, 0,5 означает выход из позиции покупки или остальное наличными, -1 означает короткий или короткий, а -0,5 означает выход из короткого или оставшегося купюрами. – geronimo
Я добавил несколько примеров данных и желаемых результатов. Пожалуйста, дайте мне знать, если потребуется дополнительное разъяснение. – geronimo