向量化/优化此python代码的最佳方法是什么?
我通过一次迭代和计算每个列来计算48个派生的pandas列,但需要加快过程。要使其更快、更有效,最好的方法是什么。每列计算收盘价占该期间(T、T-1、T-2等)高价和低价的百分比 我目前使用的代码是:向量化/优化此python代码的最佳方法是什么?,python,optimization,vectorization,Python,Optimization,Vectorization,我通过一次迭代和计算每个列来计算48个派生的pandas列,但需要加快过程。要使其更快、更有效,最好的方法是什么。每列计算收盘价占该期间(T、T-1、T-2等)高价和低价的百分比 我目前使用的代码是: #get last x closes as percentage of period high and low for i in range(1, 49, 1): df.loc[:,'Close_T_period_'+str(i)] = ((df['BidClose'].shift(i).
#get last x closes as percentage of period high and low
for i in range(1, 49, 1):
df.loc[:,'Close_T_period_'+str(i)] = ((df['BidClose'].shift(i).values
- df['BidLow'].shift(i).values)/
(df['BidHigh'].shift(i).values - df['BidLow'].shift(i).values))
输入数据帧示例:
BidOpen BidHigh BidLow BidClose AskOpen AskHigh AskLow AskClose Volume
Date
2019-09-27 09:00:00 1.22841 1.22919 1.22768 1.22893 1.22850 1.22927 1.22777 1.22900 12075.0
2019-09-27 10:00:00 1.22893 1.23101 1.22861 1.23058 1.22900 1.23110 1.22870 1.23068 16291.0
2019-09-27 11:00:00 1.23058 1.23109 1.22971 1.23076 1.23068 1.23119 1.22979 1.23087 10979.0
2019-09-27 12:00:00 1.23076 1.23308 1.23052 1.23232 1.23087 1.23314 1.23062 1.23241 16528.0
2019-09-27 13:00:00 1.23232 1.23247 1.23163 1.23217 1.23241 1.23256 1.23172 1.23228 14106.0
BidOpen BidHigh BidLow BidClose ... Close_T_period_45 Close_T_period_46 Close_T_period_47 Close_T_period_48
Date ...
2019-09-27 09:00:00 1.22841 1.22919 1.22768 1.22893 ... 0.682635 0.070796 0.128940 0.794521
2019-09-27 10:00:00 1.22893 1.23101 1.22861 1.23058 ... 0.506024 0.682635 0.070796 0.128940
2019-09-27 11:00:00 1.23058 1.23109 1.22971 1.23076 ... 0.774920 0.506024 0.682635 0.070796
2019-09-27 12:00:00 1.23076 1.23308 1.23052 1.23232 ... 0.212500 0.774920 0.506024 0.682635
2019-09-27 13:00:00 1.23232 1.23247 1.23163 1.23217 ... 0.378882 0.212500 0.774920 0.506024
输出数据帧示例:
BidOpen BidHigh BidLow BidClose AskOpen AskHigh AskLow AskClose Volume
Date
2019-09-27 09:00:00 1.22841 1.22919 1.22768 1.22893 1.22850 1.22927 1.22777 1.22900 12075.0
2019-09-27 10:00:00 1.22893 1.23101 1.22861 1.23058 1.22900 1.23110 1.22870 1.23068 16291.0
2019-09-27 11:00:00 1.23058 1.23109 1.22971 1.23076 1.23068 1.23119 1.22979 1.23087 10979.0
2019-09-27 12:00:00 1.23076 1.23308 1.23052 1.23232 1.23087 1.23314 1.23062 1.23241 16528.0
2019-09-27 13:00:00 1.23232 1.23247 1.23163 1.23217 1.23241 1.23256 1.23172 1.23228 14106.0
BidOpen BidHigh BidLow BidClose ... Close_T_period_45 Close_T_period_46 Close_T_period_47 Close_T_period_48
Date ...
2019-09-27 09:00:00 1.22841 1.22919 1.22768 1.22893 ... 0.682635 0.070796 0.128940 0.794521
2019-09-27 10:00:00 1.22893 1.23101 1.22861 1.23058 ... 0.506024 0.682635 0.070796 0.128940
2019-09-27 11:00:00 1.23058 1.23109 1.22971 1.23076 ... 0.774920 0.506024 0.682635 0.070796
2019-09-27 12:00:00 1.23076 1.23308 1.23052 1.23232 ... 0.212500 0.774920 0.506024 0.682635
2019-09-27 13:00:00 1.23232 1.23247 1.23163 1.23217 ... 0.378882 0.212500 0.774920 0.506024
简短回答(更快的实施)
以下代码速度快6倍:
import numpy as np
def my_shift(x, i):
first = np.array([np.nan]*i)
return np.append(first, x[:-i])
result = ((df2['BidClose'].values - df2['BidLow'].values)/(df2['BidHigh'].values - df2['BidLow'].values))
for i in range(1, 49, 1):
df2.loc[:,'Close_T_period_'+str(i)] = my_shift(result, i)
长答覆(解释)
代码中的两个主要瓶颈问题是:
I
NaN值之前追加,并剪切最后一个I
执行时间
对于5000行的数据帧,时间基准给出:
42 ms ± 1.79 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
通过我的解决方案,我得到:
7.62 ms ± 140 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
更新
我尝试使用apply实现一个解决方案:
result = ((df2['BidClose'].values - df2['BidLow'].values)/(df2['BidHigh'].values - df2['BidLow'].values))
df3 = df.reindex(df2.columns.tolist() +[f'Close_T_period_{i}' for i in range(1, 2000)], axis=1)
df3.iloc[:, 9:] = df3.iloc[:, 9:].apply(lambda row: my_shift(result, int(row.name.split('_')[-1])))
在我的测试中,此解决方案似乎比第一个稍慢。欢迎使用此解决方案!考虑更新您的问题,更好地解释您的问题,您的代码应该做什么,并添加一些输入/输出示例。谢谢法比奥。我可以提供熊猫输入和输出的示例,但如何在此处共享/粘贴?您可以打印数据集的标题或大量行,例如使用:
print(df.head())
。将结果以代码的形式粘贴到这里。根据建议添加了输入和输出尾部示例。感谢您的支持。这是可以完全矢量化的东西吗?删除“for”迭代还是不可能或不合适?我不知道矢量化的方法,问题是在每个循环上创建一个新列。好的。我一直在尝试将其矢量化,但不太清楚如何实现。听到这是因为这是不可能的,我有点安慰。无论如何,6倍的速度对我来说是好的。再次感谢您的帮助Fabio:-)还有一件事Fabio-您认为您的解决方案可以通过尝试使用“应用”而不是“for”循环来进一步改进吗?Fabiol-现在我能够+1您的有用答案。再次感谢