如何向量化pandas循环计算DataFrame的x日高低点并提升性能
概述
我需要为DataFrame的每一行计算x日高点和x日低点。
x日高点指该值高于此前连续x天的对应高点,x日低点指该值低于此前连续x天的对应低点。
更新
此前@mozway给出的答案在包含1.8万行的数据集上运行耗时约20秒,请问能否通过numpy广播等技术进一步优化性能?
示例
2020-03-20的x_day_low值为1,因为其价格低于前1天的低点。2020-03-27的x_day_high值为8,因为其价格高于前8天的高点。
下文给出了期望输出结果,以及通过for循环实现的findHighLow函数对应的测试代码。由于实际使用的DataFrame体量较大,请问如何对findHighLow进行向量化改造?
测试数据
import pandas as pd import numpy as np def genMockDataFrame(days,startPrice,colName,startDate,seed=None): periods = days*24 np.random.seed(seed) steps = np.random.normal(loc=0, scale=0.0018, size=periods) steps[0]=0 P = startPrice+np.cumsum(steps) P = [round(i,4) for i in P] fxDF = pd.DataFrame({ 'ticker':np.repeat( [colName], periods ), 'date':np.tile( pd.date_range(startDate, periods=periods, freq='H'), 1 ), 'price':(P)}) fxDF.index = pd.to_datetime(fxDF.date) fxDF = fxDF.price.resample('D').ohlc() fxDF.columns = [i.title() for i in fxDF.columns] return fxDF # 最小示例设置为15行,实际DataFrame约有18000行 number_of_rows = 15 df = genMockDataFrame(number_of_rows,1.1904,'tttmmm','19/3/2020',seed=157) def findHighLow (df): df['x_day_high'] = 0 df['x_day_low'] = 0 for n in reversed(range(len(df['High']))): for i in reversed(range(n)): if df['High'][n] > df['High'][i]: df['x_day_high'][n] = n - i else: break for n in reversed(range(len(df['Low']))): for i in reversed(range(n)): if df['Low'][n] < df['Low'][i]: df['x_day_low'][n] = n - i else: break return df df = findHighLow(df)
期望输出
最终输出需要和以下结果完全一致:
df[["High","Low","x_day_high","x_day_low"]] High Low x_day_high x_day_low date 2020-03-19 1.1937 1.1832 0 0 2020-03-20 1.1879 1.1769 0 1 2020-03-21 1.1767 1.1662 0 2 2020-03-22 1.1721 1.1611 0 3 2020-03-23 1.1819 1.1690 2 0 2020-03-24 1.1928 1.1807 4 0 2020-03-25 1.1939 1.1864 6 0 2020-03-26 1.2141 1.1964 7 0 2020-03-27 1.2144 1.2039 8 0 2020-03-28 1.2099 1.2018 0 1 2020-03-29 1.2033 1.1853 0 4 2020-03-30 1.1887 1.1806 0 6 2020-03-31 1.1972 1.1873 1 0 2020-04-01 1.1997 1.1914 2 0 2020-04-02 1.1924 1.1781 0 9
内容的提问来源于stack exchange,提问作者nipy
相关产品推荐
相关产品推荐

