pct_change 无法在 Pandas 中使用 .rolling() 的解决方法?
Workaround for pct_change not working with .rolling() in Pandas?
我有一个超过 2 毫米行的数据框。它具有过去 20 年标准普尔 500 指数所有股票的调整后收盘价(因此,companies/tickers 的混合)。底部是我的数据框的快照。我将把这些数据放入一个预测模型中,该模型使用各种动量列作为其特征,它将尝试预测一只股票是否可能有 6% 以上的月度 return。然而,生产合适的“动量柱”被证明是困难的。
“one_month_6_pct+_gain”列是我的目标,它源自“21_day_performance”列。我的动量列无法“看到”该数据。
下面的代码用于生成使用当前行信息的列(我不必移动)。
df['daily_performance'] = df.groupby('Ticker').adj_close.pct_change().fillna(0)
df['twenty_one_day_performance'] = df.groupby('Ticker').adj_close.pct_change(periods=21).fillna(0)
df.loc[df['twenty_one_day_performance'] >= 0.06, 'one_month_6_pct+_gain'] = "Yes"
df.loc[df['twenty_one_day_performance'] < 0.06, 'one_month_6_pct+_gain'] = "No"
但是,当我尝试创建基于前几天(未“看到”我之前提到的 21 天)的 adj_close 的新列时,我遇到了各种问题。
这很接近,但是,在这里使用“sum()”是不正确的。如果一只股票第一天的交易价格为 20 美元,第二天上涨 100%,它将达到 40 美元。但是,如果它在第三天下跌 100%,它将是 0 美元,而不是 20 美元。所以,这里求和是不正确的。但它和我得到的一样接近工作代码。
df['preceeding_5_day_perf']=df.groupby('Ticker').daily_performance.rolling(26).sum().fillna(0).reset_index(0,drop=True)-df.groupby('Ticker').daily_performance.rolling(21).sum().fillna(0).reset_index(0,drop=True)
如果在 rolling() 之后支持 pct_change(),我认为下面的方法会起作用。但是,我得到“'RollingGroupby' 对象没有属性 'pct_change'”
df['preceeding_5_day_perf']=df.groupby('Ticker').adj_close.rolling(26).pct_change().fillna(0).reset_index(0,drop=True)-df.groupby('Ticker').adj_close.rolling(21).pct_change().fillna(0).reset_index(0,drop=True)
下面报错。 “类型错误:- 的操作数类型不受支持:'RollingGroupby' 和 'RollingGroupby'”
df['preceeding_5_day_perf']=df.groupby('Ticker').adj_close.rolling(26)-df.groupby('Ticker').adj_close.rolling(21)
下面很接近,但是,它给出了 21 到 26 之间 5 天的 negated/opposite 值“twenty_one_day_performance”。我希望它为这 5 天提供 0.0。
df['preceeding_5_day_perf'] = (df.groupby('Ticker').adj_close.pct_change(periods=26).fillna(0)) - (df.groupby('Ticker').adj_close.pct_change(periods=21).fillna(0))
下方也很接近,但是,由于 df 中有 500 只不同的股票,当一只股票结束而另一只股票开始时,这是一个问题。在您考虑重叠 stocks/tickers 问题之前,下面的方法一直有效。我不知道如何让 groupby 在这里工作。
preceeding_5_day_perf = (df['adj_close'].shift(26) - df['adj_close'].shift(21)) / df['adj_close'].shift(21)
df = df.assign(preceeding_5_day_perf=preceeding_5_day_perf)
我的数据框的一个小样本:
Index Date High Low adj_close Ticker daily_performance 21_day_performance one_month_6_pct+_gain
8930 2020-10-15 35.380001 33.639999 34.250000 UAL -0.038192 -0.105744 No
8931 2000-01-03 18.625000 17.312500 10.834452 TROW 0.000000 0.000000 No
8932 2000-01-04 17.562500 17.000000 10.506723 TROW -0.030249 0.000000 No
8933 2000-01-05 17.468750 16.593750 10.487448 TROW -0.001835 0.000000 No
8934 2000-01-06 17.500000 16.687500 10.795900 TROW 0.029412 0.000000 No
8935 2000-01-07 17.750000 17.250000 10.718788 TROW -0.007143 0.000000 No
8936 2000-01-10 17.875000 17.437500 10.834452 TROW 0.010791 0.000000 No
8937 2000-01-11 17.781250 17.281250 10.795900 TROW -0.003558 0.000000 No
8938 2000-01-12 18.250000 17.593750 11.258587 TROW 0.042858 0.000000 No
8939 2000-01-13 19.843750 18.296875 11.875495 TROW 0.054794 0.000000 No
8940 2000-01-14 19.562500 19.187500 12.048991 TROW 0.014610 0.000000 No
8941 2000-01-18 19.437500 18.593750 11.586312 TROW -0.038400 0.000000 No
8942 2000-01-19 19.625000 18.812500 11.759820 TROW 0.014975 0.000000 No
8943 2000-01-20 19.312500 18.875000 11.759820 TROW 0.000000 0.000000 No
8944 2000-01-21 20.093750 19.187500 12.318892 TROW 0.047541 0.000000 No
8945 2000-01-24 20.937500 19.625000 12.183943 TROW -0.010955 0.000000 No
8946 2000-01-25 21.250000 19.250000 13.070749 TROW 0.072785 0.000000 No
8947 2000-01-26 21.312500 19.812500 12.955079 TROW -0.008850 0.000000 No
8948 2000-01-27 21.437500 19.593750 12.106827 TROW -0.065476 0.000000 No
8949 2000-01-28 19.687500 18.187500 11.258587 TROW -0.070063 0.000000 No
8950 2000-01-31 19.437500 17.937500 11.991161 TROW 0.065068 0.000000 No
8951 2000-02-01 19.656250 18.687500 12.068275 TROW 0.006431 0.000000 No
8952 2000-02-02 19.875000 19.000000 12.222500 TROW 0.012779 0.128114 Yes
8953 2000-02-03 20.062500 18.750000 11.856213 TROW -0.029968 0.128441 Yes
8954 2000-02-04 19.375000 18.406250 11.451367 TROW -0.034146 0.091912 Yes
8955 2000-02-07 19.406250 18.281250 11.316417 TROW -0.011785 0.048214 No
8956 2000-02-08 18.625000 18.250000 11.316417 TROW 0.000000 0.055755 No
8957 2000-02-09 18.750000 17.812500 11.085073 TROW -0.020443 0.023132 No
8958 2000-02-10 18.437500 17.750000 11.007962 TROW -0.006956 0.019643 No
8959 2000-02-11 18.000000 17.500000 10.824816 TROW -0.016638 -0.038528 No
8960 2000-02-14 17.718750 16.593750 10.391053 TROW -0.040071 -0.125000 No
我最终通过创建新的数据帧找到了解决这个问题的方法。我确定有更好的解决方案。
#creating an array of tickers
unique_tickers = df.Ticker.unique()
#creating a dictionary to be used in a for loop
companydict = {elem : pd.DataFrame() for elem in unique_tickers}
for key in companydict.keys():
companydict[key] = df[:][df.Ticker == key]
#creating the 5 day performance column that preceeds the 21 day prediction period
preceeding_5_day_perf = (companydict[key]['adj_close'].shift(21) - companydict[key]['adj_close'].shift(26)) / companydict[key]['adj_close'].shift(26)
companydict[key] = companydict[key].assign(preceeding_5_day_perf=preceeding_5_day_perf).fillna(0)
#creating a new df for each ticker (eg. CSCO ticker will be in df_CSCO)
globals()['df_{}'.format(key)] = companydict[key]
然后,我刚刚创建了所有 dfs 的列表,并使用 concat 垂直组合所有数据帧。
df_final = pd.concat(df_list)
如果在 Pandas 中的 rolling() 之后支持 pct_change(),这会容易得多。
我有一个超过 2 毫米行的数据框。它具有过去 20 年标准普尔 500 指数所有股票的调整后收盘价(因此,companies/tickers 的混合)。底部是我的数据框的快照。我将把这些数据放入一个预测模型中,该模型使用各种动量列作为其特征,它将尝试预测一只股票是否可能有 6% 以上的月度 return。然而,生产合适的“动量柱”被证明是困难的。
“one_month_6_pct+_gain”列是我的目标,它源自“21_day_performance”列。我的动量列无法“看到”该数据。
下面的代码用于生成使用当前行信息的列(我不必移动)。
df['daily_performance'] = df.groupby('Ticker').adj_close.pct_change().fillna(0)
df['twenty_one_day_performance'] = df.groupby('Ticker').adj_close.pct_change(periods=21).fillna(0)
df.loc[df['twenty_one_day_performance'] >= 0.06, 'one_month_6_pct+_gain'] = "Yes"
df.loc[df['twenty_one_day_performance'] < 0.06, 'one_month_6_pct+_gain'] = "No"
但是,当我尝试创建基于前几天(未“看到”我之前提到的 21 天)的 adj_close 的新列时,我遇到了各种问题。
这很接近,但是,在这里使用“sum()”是不正确的。如果一只股票第一天的交易价格为 20 美元,第二天上涨 100%,它将达到 40 美元。但是,如果它在第三天下跌 100%,它将是 0 美元,而不是 20 美元。所以,这里求和是不正确的。但它和我得到的一样接近工作代码。
df['preceeding_5_day_perf']=df.groupby('Ticker').daily_performance.rolling(26).sum().fillna(0).reset_index(0,drop=True)-df.groupby('Ticker').daily_performance.rolling(21).sum().fillna(0).reset_index(0,drop=True)
如果在 rolling() 之后支持 pct_change(),我认为下面的方法会起作用。但是,我得到“'RollingGroupby' 对象没有属性 'pct_change'”
df['preceeding_5_day_perf']=df.groupby('Ticker').adj_close.rolling(26).pct_change().fillna(0).reset_index(0,drop=True)-df.groupby('Ticker').adj_close.rolling(21).pct_change().fillna(0).reset_index(0,drop=True)
下面报错。 “类型错误:- 的操作数类型不受支持:'RollingGroupby' 和 'RollingGroupby'”
df['preceeding_5_day_perf']=df.groupby('Ticker').adj_close.rolling(26)-df.groupby('Ticker').adj_close.rolling(21)
下面很接近,但是,它给出了 21 到 26 之间 5 天的 negated/opposite 值“twenty_one_day_performance”。我希望它为这 5 天提供 0.0。
df['preceeding_5_day_perf'] = (df.groupby('Ticker').adj_close.pct_change(periods=26).fillna(0)) - (df.groupby('Ticker').adj_close.pct_change(periods=21).fillna(0))
下方也很接近,但是,由于 df 中有 500 只不同的股票,当一只股票结束而另一只股票开始时,这是一个问题。在您考虑重叠 stocks/tickers 问题之前,下面的方法一直有效。我不知道如何让 groupby 在这里工作。
preceeding_5_day_perf = (df['adj_close'].shift(26) - df['adj_close'].shift(21)) / df['adj_close'].shift(21)
df = df.assign(preceeding_5_day_perf=preceeding_5_day_perf)
我的数据框的一个小样本:
Index Date High Low adj_close Ticker daily_performance 21_day_performance one_month_6_pct+_gain
8930 2020-10-15 35.380001 33.639999 34.250000 UAL -0.038192 -0.105744 No
8931 2000-01-03 18.625000 17.312500 10.834452 TROW 0.000000 0.000000 No
8932 2000-01-04 17.562500 17.000000 10.506723 TROW -0.030249 0.000000 No
8933 2000-01-05 17.468750 16.593750 10.487448 TROW -0.001835 0.000000 No
8934 2000-01-06 17.500000 16.687500 10.795900 TROW 0.029412 0.000000 No
8935 2000-01-07 17.750000 17.250000 10.718788 TROW -0.007143 0.000000 No
8936 2000-01-10 17.875000 17.437500 10.834452 TROW 0.010791 0.000000 No
8937 2000-01-11 17.781250 17.281250 10.795900 TROW -0.003558 0.000000 No
8938 2000-01-12 18.250000 17.593750 11.258587 TROW 0.042858 0.000000 No
8939 2000-01-13 19.843750 18.296875 11.875495 TROW 0.054794 0.000000 No
8940 2000-01-14 19.562500 19.187500 12.048991 TROW 0.014610 0.000000 No
8941 2000-01-18 19.437500 18.593750 11.586312 TROW -0.038400 0.000000 No
8942 2000-01-19 19.625000 18.812500 11.759820 TROW 0.014975 0.000000 No
8943 2000-01-20 19.312500 18.875000 11.759820 TROW 0.000000 0.000000 No
8944 2000-01-21 20.093750 19.187500 12.318892 TROW 0.047541 0.000000 No
8945 2000-01-24 20.937500 19.625000 12.183943 TROW -0.010955 0.000000 No
8946 2000-01-25 21.250000 19.250000 13.070749 TROW 0.072785 0.000000 No
8947 2000-01-26 21.312500 19.812500 12.955079 TROW -0.008850 0.000000 No
8948 2000-01-27 21.437500 19.593750 12.106827 TROW -0.065476 0.000000 No
8949 2000-01-28 19.687500 18.187500 11.258587 TROW -0.070063 0.000000 No
8950 2000-01-31 19.437500 17.937500 11.991161 TROW 0.065068 0.000000 No
8951 2000-02-01 19.656250 18.687500 12.068275 TROW 0.006431 0.000000 No
8952 2000-02-02 19.875000 19.000000 12.222500 TROW 0.012779 0.128114 Yes
8953 2000-02-03 20.062500 18.750000 11.856213 TROW -0.029968 0.128441 Yes
8954 2000-02-04 19.375000 18.406250 11.451367 TROW -0.034146 0.091912 Yes
8955 2000-02-07 19.406250 18.281250 11.316417 TROW -0.011785 0.048214 No
8956 2000-02-08 18.625000 18.250000 11.316417 TROW 0.000000 0.055755 No
8957 2000-02-09 18.750000 17.812500 11.085073 TROW -0.020443 0.023132 No
8958 2000-02-10 18.437500 17.750000 11.007962 TROW -0.006956 0.019643 No
8959 2000-02-11 18.000000 17.500000 10.824816 TROW -0.016638 -0.038528 No
8960 2000-02-14 17.718750 16.593750 10.391053 TROW -0.040071 -0.125000 No
我最终通过创建新的数据帧找到了解决这个问题的方法。我确定有更好的解决方案。
#creating an array of tickers
unique_tickers = df.Ticker.unique()
#creating a dictionary to be used in a for loop
companydict = {elem : pd.DataFrame() for elem in unique_tickers}
for key in companydict.keys():
companydict[key] = df[:][df.Ticker == key]
#creating the 5 day performance column that preceeds the 21 day prediction period
preceeding_5_day_perf = (companydict[key]['adj_close'].shift(21) - companydict[key]['adj_close'].shift(26)) / companydict[key]['adj_close'].shift(26)
companydict[key] = companydict[key].assign(preceeding_5_day_perf=preceeding_5_day_perf).fillna(0)
#creating a new df for each ticker (eg. CSCO ticker will be in df_CSCO)
globals()['df_{}'.format(key)] = companydict[key]
然后,我刚刚创建了所有 dfs 的列表,并使用 concat 垂直组合所有数据帧。
df_final = pd.concat(df_list)
如果在 Pandas 中的 rolling() 之后支持 pct_change(),这会容易得多。