pandas调用df.apply填充DataFrame列时部分行返回NaN如何解决
问题原因与解决方案
首先明确:你遇到的NaN不是格式问题,由两个代码逻辑错误导致:
错误1:未定义变量i
你在set_order_signal函数内使用了df.iloc[i-1],但i并没有在函数内定义,也没有作为参数传入。df.apply按行遍历的时候仅会向函数传入当前行的row对象,无法直接获取当前行的索引位置,你对i的调用属于未定义行为,会导致逻辑判断失效。
错误2:分支逻辑覆盖不全
你当前的逻辑仅覆盖了4种分支中的3种:
- 外层if条件成立+内层if条件成立 → 返回1
- 外层elif条件成立+内层if条件成立 → 返回-1
- 外层if、elif都不成立 → 返回0
- 外层if/elif成立但内层if不成立:这种情况你没有写任何return语句,Python函数默认返回
None,pandas会自动将None转换为NaN,这是你得到NaN的核心原因。
优化解决方案(推荐,比apply效率高10倍以上)
不要用apply遍历行,直接用pandas的shift方法获取前一行的指标值,配合向量化条件判断实现需求:
import numpy as np # 生成前一行的MACD、SIGNAL列,shift(1)代表将列整体下移1行,第0行前值为NaN df['prev_MACD'] = df['MACD'].shift(1) df['prev_SIGNAL'] = df['SIGNAL'].shift(1) # 定义多条件 # 做多信号条件 long_cond = (df['MACD'] > df['SIGNAL']) & \ (df['prev_MACD'] < df['prev_SIGNAL']) & \ (df['MACD'] < 0) & (df['SIGNAL'] < 0) & \ (df['close'] > df['200EMA']) # 做空信号条件 short_cond = (df['MACD'] < df['SIGNAL']) & \ (df['prev_MACD'] > df['prev_SIGNAL']) & \ (df['MACD'] > 0) & (df['SIGNAL'] > 0) & \ (df['close'] < df['200EMA']) # 赋值:满足做多信号返回1,做空返回-1,其余返回0 df['OrderSignal'] = np.where(long_cond, 1, np.where(short_cond, -1, 0))
如果你坚持使用apply的修正写法
可以通过row.name获取当前行的索引,同时补全所有分支的返回值:
def set_order_signal(row): # 第0行没有前一行数据,直接返回0 if row.name == 0: return 0 # 获取前一行数据 prev_row = df.iloc[row.name - 1] # 金叉判断 if (row.MACD > row.SIGNAL) and (prev_row.MACD < prev_row.SIGNAL): return 1 if (row.MACD < 0 and row.SIGNAL < 0) and (row.close > row['200EMA']) else 0 # 死叉判断 elif (row.MACD < row.SIGNAL) and (prev_row.MACD > prev_row.SIGNAL): return -1 if (row.MACD > 0 and row.SIGNAL > 0) and (row.close < row['200EMA']) else 0 # 其余情况返回0 else: return 0 # 调用apply df['OrderSignal'] = df.apply(set_order_signal, axis=1)
内容的提问来源于stack exchange,提问作者Erwin109
相关产品推荐
相关产品推荐

