Python中如何提取DataFrame上一行的元素?
解决方案
你的问题核心在于用apply(axis=1)逐行处理时,函数内拿到的是单行Series,无法直接获取上一行数据,而且iloc[3]在这里取的是当前行的第3个元素,完全不是你要的上一行entry值。
Pandas里处理“上一行数据”的标准方法是用shift()函数,它可以直接将列数据整体下移一行,从而轻松获取上一行的值。同时,避免用apply逐行循环,改用向量化操作,效率会高很多。
修正后的代码
import numpy as np # 第一步:初始化entry列,处理第一个条件(8maUP=1且8maUP1=0时取close) sp500['entry'] = np.where( (sp500['8maUP'] == 1) & (sp500['8maUP1'] == 0), sp500['close'], np.nan ) # 第二步:处理第二个条件(8maUP和8maUP1都为1时,取上一行的entry值) sp500['entry'] = np.where( (sp500['8maUP'] == 1) & (sp500['8maUP1'] == 1), sp500['entry'].shift(1), sp500['entry'] ) # 第三步:将剩余的空值替换为0(对应else的情况) sp500['entry'] = sp500['entry'].fillna(0)
代码说明
shift(1):将entry列的数据向下移动一行,此时sp500['entry'].shift(1)[i]就是原DataFrame中第i-1行的entry值。np.where:向量化的条件判断,比逐行循环高效得多,适合处理DataFrame的批量条件赋值。- 最后用
fillna(0)处理所有不满足前两个条件的情况,对应你原代码中的else: return '0'。
如果一定要用apply(不推荐,效率低)
如果你坚持要保留apply的写法,需要在函数中传入当前行的索引,通过索引减1来获取上一行数据:
def entry1(row): idx = row.name if row['8maUP'] == 1 and row['8maUP1'] == 0: return row['close'] elif row['8maUP'] == 1 and row['8maUP1'] == 1: # 处理第一行的边界情况,索引为0时没有上一行,返回0 return sp500.loc[idx-1, 'entry'] if idx > 0 else 0 else: return 0 sp500['entry'] = sp500.apply(entry1, axis=1)
这种方法需要注意第一行的边界问题,而且逐行循环的速度远低于向量化操作,不建议用于大数据量的回测。
内容的提问来源于stack exchange,提问作者Bugsy
相关产品推荐
相关产品推荐

