【问题标题】:Very slow computation on a Dataframe based on previous rows基于先前行的 Dataframe 计算速度非常慢
【发布时间】:2021-06-30 20:26:40
【问题描述】:

我正在计算当前行的结果需要前一行的股票价格的 RSI 值。我目前正在通过 for 循环完整数据帧多次执行此操作,这些条目需要花费大量时间(在我的电脑上执行时间大约为 15 秒)。

有没有办法改进该代码?

import pandas as pd
from pathlib import Path


filename = Path("Tesla.csv")
test = pd.read_csv(filename)
data = pd.DataFrame(test[["Date","Close"]])
data["Change"] = (data["Close"].shift(-1)-data["Close"]).shift(1)
data["Gain"] = 0.0
data["Loss"] = 0.0
data.loc[data["Change"] >= 0, "Gain"] = data["Change"]
data.loc[data["Change"] <= 0, "Loss"] = data["Change"]*-1
data.loc[:, "avgGain"] = 0.0
data.loc[:, "avgLoss"] = 0.0
data["avgGain"].iat[14] = data["Gain"][1:15].mean()
data["avgLoss"].iat[14] = data["Loss"][1:15].mean()


for index in data.iterrows():
    data.loc[15:, "avgGain"] = (data.loc[14:, "avgGain"].shift(1)*13 + data.loc[15:, "Gain"])/14
    data.loc[15:, "avgLoss"] = (data.loc[14:, "avgLoss"].shift(1)*13 + data.loc[15:, "Loss"])/14

使用的数据集可以在这里下载: TSLA historic dataset from yahoo finance

目标是根据要计算的 avgGain 和 avgLoss 值计算 RSI 值。 0:14 行的 avgGain 值不存在。 第 15 行的 avgGain 值是 Gain 列的第 [1:14] 行的平均值。 从第 16 行开始的 avgGain 值计算如下: (13*avgGain(前行)+增益(当前行))/14

【问题讨论】:

  • 您可以通过使用apply 而不是遍历行来加快速度。
  • 我并不完全清楚这个循环试图实现什么。 index 从未实际使用过。看起来两条线在循环之外可以实现同样的事情。
  • 您能否提供一个包含小数据集的可重现示例?
  • 我用一个例子更新了我的初始帖子
  • 您能否将tesla.csv 中的一些数据手动输入到脚本中,或者将其上传到互联网上的某个位置,例如谷歌驱动器电子表格。它仍然无法重现。

标签: python pandas performance


【解决方案1】:

'itertuples' 比 'iterrows' 快,并且矢量化操作通常在 time 方面表现最好。

在这里,您可以使用窗口大小为 14 的 rolling 方法计算 14 天的平均收益和损失(滚动平均值)。

%%timeit
data["avgGain"].iat[14] = data["Gain"][1:15].mean()
data["avgLoss"].iat[14] = data["Loss"][1:15].mean()

for index in data.iterrows():
    data.loc[15:, "avgGain"] = (data.loc[14:, "avgGain"].shift(1)*13 + data.loc[15:, "Gain"])/14
    data.loc[15:, "avgLoss"] = (data.loc[14:, "avgLoss"].shift(1)*13 + data.loc[15:, "Loss"])/14

每个循环 1.12 秒 ± 3.73 毫秒(平均值 ± 标准偏差。7 次运行,每个循环 1 个)

%%timeit
data['avgGain_alt'] = data['Gain'].rolling(window=14).mean().fillna(0)
data['avgLos_alt'] = data['Gain'].rolling(window=14).mean().fillna(0)

每个循环 1.38 ms ± 2.31 µs(7 次运行的平均值 ± 标准偏差,每次 1000 个循环)

data.head(15)

使用矢量化运算计算移动平均值比使用循环计算快大约 10 倍。

但是请注意,在您的代码中,对于第一个平均值之后的平均值,也存在一些计算错误。

【讨论】:

  • 我已经看到了滚动函数(结合平均函数),但它没有给出相同的值。简单地说,我需要的函数是: newAvgGainValue = (lastAvgGainValue*13+currentGainValue)/14 这会导致第一个值对最后一个值的影响。恕我直言,这没有多大意义,但这就是它的计算方式。 (好吧,还有其他一些方法可以计算 RSI 的滚动平均值,但比较主页使用上面提到的计算)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
  • 2014-08-28
  • 2019-04-10
  • 1970-01-01
  • 2021-10-19
相关资源
最近更新 更多