如何用Pandas高效实现纳尔逊第3法则(Nelson's Rule 3)
用Pandas高效实现纳尔逊第3法则(标记所有符合条件的数据点)
纳尔逊第3法则要求识别连续6个持续递增或递减的数据点,你的初始方法只能标记序列的最后一个点,核心问题是滚动窗口仅向后验证,未覆盖序列中的前置点。以下是基于Pandas向量化操作的高效解决方案,无需低效的逐行遍历:
实现思路
- 通过
diff()生成数据点间的增减布尔序列; - 用滚动窗口找到所有满足「连续5个递增/递减差值」的位置(对应原数据6个连续点);
- 将每个符合条件的窗口对应的所有原数据点标记为True,通过范围赋值实现批量标记。
完整代码
import pandas as pd # 示例数据 data = pd.DataFrame({"values": [1,2,3,4,5,6,7,5,6,5,3]}) def mark_nelson_rule3(df, col='values'): # 1. 生成递增/递减布尔序列(diff后第一个值为NaN,不影响后续滚动计算) incr = df[col].diff() > 0 decr = df[col].diff() < 0 # 2. 标记所有符合连续6个递增的点 incr_mark = pd.Series(False, index=df.index) # 滚动窗口大小为5:对应原数据6个连续递增点(需要5个连续的递增差值) incr_windows = incr.rolling(5, min_periods=5).sum() == 5 # 为每个符合条件的窗口,批量标记对应的原数据点 for idx in incr_windows[incr_windows].index: incr_mark.loc[idx-5 : idx] = True # 3. 标记所有符合连续6个递减的点 decr_mark = pd.Series(False, index=df.index) decr_windows = decr.rolling(5, min_periods=5).sum() == 5 for idx in decr_windows[decr_windows].index: decr_mark.loc[idx-5 : idx] = True # 4. 合并递增/递减的标记结果 return incr_mark | decr_mark # 应用函数并输出结果 nelson_rule3 = mark_nelson_rule3(data) print(nelson_rule3)
输出结果
0 True 1 True 2 True 3 True 4 True 5 True 6 True 7 False 8 False 9 False 10 False dtype: bool
关键说明
- 滚动窗口大小设为5:因为原数据连续6个递增点,对应
diff()后会产生5个连续的True值; - 范围赋值
loc[idx-5 : idx]:将每个符合条件的窗口对应的原数据点全部标记,避免仅标记最后一个点; - 整体效率:仅在最后遍历符合条件的窗口位置(通常数量极少),核心逻辑依赖Pandas向量化操作,远快于
iterrows()或自定义apply()。
内容的提问来源于stack exchange,提问作者Oliver Cohen
相关产品推荐
相关产品推荐

