我远不是熊猫专家。我是一个普通的开发人员。
我想计算一个托管值。 我有一个df是每天的市场价格(以日期为索引)和dfTrend,它是0和1,具有相同的索引。
我想将这些数据帧发送到函数并获取托管值,这意味着当趋势为零时,我希望托管值保持平坦,当趋势为1时,我希望值增加并遵循市场价格。
我的代码工作正常,但速度很慢:
def getManagedValue(df, dfTrend):
dfReturn = df.pct_change(1)
dfManaged = df
for col in df:
for i in range(1, len(df[col])):
dfManaged[col][0] = df[col][0]
if dfTrend[col][i] == 1:
dfManaged[col][i] = dfManaged[col][i-1] * (1 + dfReturn[col][i])
else:
dfManaged[col][i] = dfManaged[col][i-1]
return dfManaged
有谁知道我如何优化它以便它运行得更快?所有列的所有单元格的迭代肯定是这里的问题。
我正在考虑使用cython运行它,但我相信我不允许使用带有cython的pandas,只有numpy的数组......
有人有建议吗?
干杯, 于连
答案 0 :(得分:1)
Pandas的速度和力量来自于对整个阵列的操作,而不是遍历各个行和单元。如果我正确地遵循原始示例中的逻辑,您可以使用np.where
更快地执行此操作:
dfManaged = np.where(dfTrend == 1, df.shift(1) * (1 + df.pct_change(1)), df.shift(1))
np.where
允许您指定一些条件(在这种情况下,dfTrend == 1
)
如果该条件为真,则从一个数据帧中分配值
(df.shift(1) * (1 + df.pct_change(1))
)和另一个
条件为假(df.shift(1)
)。 df.shift(1)
将df
中的所有值向下移动一行,例如dfManaged[col][i-1]
但不必迭代。答案 1 :(得分:0)
从我收集的内容中,您可以使用导数(df.pct_change(1)
)来重建曲线。当趋势为1
时,您希望使用此衍生产品,当0
衍生产品应为0时。
有效地完成这项工作有点棘手。一种尝试是(i)使用dfTrend
来修改导数,以及(ii)重新计算managed
作为导数的累积和。你可能会遇到一些浮点错误 - 我不确定。
# step 1
deriv = 1 + df.pct_change(1)
deriv[dfTrend == 0] = 0
# step 2
managed = np.cumsum(deriv)
# optional -- remove potential floating point errors where possible
managed[dfTrend == 1] = df[dfTrend == 1]
答案 2 :(得分:0)
感谢您的回答。我终于找到了解决方案。
数据帧为[2696行x 305列], 使用pandas数据帧处理它需要大约5分钟(使用问题中的代码)。
我使用numpy数组并且下降到2.30分钟。
最后,我对一切进行了cython化,然后下降到2.5秒,这绝对是足够好的。
干杯, 于连