计算托管值的最有效方法

时间:2017-05-18 14:44:28

标签: python python-2.7 pandas numpy scalability

我远不是熊猫专家。我是一个普通的开发人员。

我想计算一个托管值。 我有一个df是每天的市场价格(以日期为索引)和dfTrend,它是0和1,具有相同的索引。

我想将这些数据帧发送到函数并获取托管值,这意味着当趋势为零时,我希望托管值保持平坦,当趋势为1时,我希望值增加并遵循市场价格。

例如:enter image description here

我的代码工作正常,但速度很慢:

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的数组......

有人有建议吗?

干杯, 于连

3 个答案:

答案 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秒,这绝对是足够好的。

干杯, 于连