Я не думаю, что ваш код будет работать так, как задумано, потому что вы эффективно устанавливаете весь столбец df_pre_decay[xyz]
в одно значение в каждом цикле цикла.Вам нужно либо для циклического прохождения каждой строки кадра данных (for i in range(len(df_pre_decay))
), либо обрабатывать столбцы как векторы (как это делают np.where
и другие простые функции), но вы смешиваете и то, и другое.Векторизованный подход обычно будет намного быстрее.
Для не векторизованной версии установите для столбца xyz
то же самое, что и для столбца a
, а затем выполните цикл по строкам, задавая, где необходимо, значения накопления.
for a in tactic_decay_dict:
for b in tactic_decay_dict[a]:
xyz = a+'_s'+str(b)
## Loops for iterating over each row in the dataset
df_pre_decay[xyz] = df_pre_decay[a]
for i in range(len(df_pre_decay)):
if i % uniq != 0:
df_pre_decay[xyz].iloc[i] = (df_pre_decay[xyz].iloc[i-1] * b/100
+ df_pre_decay[a].iloc[i] * (100 - b)/100)
Или альтернативная версия - не уверен, что будет быстрее:
for a in tactic_decay_dict:
for b in tactic_decay_dict[a]:
xyz = a+'_s'+str(b)
column = []
for i, x in enumerate(df_pre_decay[a]):
if i % uniq == 0:
current = x
else:
current = x * b/100 + current * (100-b)/100
column.append(current)
df[xyz] = column
Для векторизации вы можете разбить столбцы на куски и применить функцию кумулятивного затухания к каждому, используяnumpy.ufunc.accumulate
.
for a in tactic_decay_dict:
for b in tactic_decay_dict[a]:
xyz = a+'_s'+str(b)
decay_func = np.frompyfunc(lambda u, v: u * b / 100.0 + v * (100-b) / 100.0, 2, 1)
decayed = np.array([])
for top in range(0, len(df_pre_decay), uniq):
chunk = df_pre_decay[a][top:top+uniq]
decayed = np.concatenate((decayed,
decay_func.accumulate(chunk, dtype=np.object).astype(np.float)))
df_pre_decay[xyz] = decayed
Альтернативный способ - вставить пустые строки с нулевыми значениями между различными идентификаторами.Затем вы можете применить одну функцию накопления ко всем столбцам:
# insert blank rows in the data
df.index = df.index + df.index // uniq
df.reindex(index=range(len(df) + len(df) // uniq))
def get_decay_func(b):
def inner(u, v):
if pd.isnull(u) or pd.isnull(v):
return v
else:
return u * b/100.0 + v * (100-b)/100.0
return inner
for a in tactic_decay_dict:
for b in tactic_decay_dict[a]:
decay = get_decay_func(b).accumulate
xyz = a+'_s'+str(b)
df_pre_decay[xyz] = decay(df_pre_decay[a], dtype=np.object).astype(df.float)