如何基于Pandas当前列值为np.where设置条件?附示例DataFrame
用Pandas实现状态延续的TEST列逻辑
嘿,我太懂这种感觉了——Excel里靠拖拽公式就能搞定的状态延续逻辑,到Pandas里一开始确实容易卡壳。先把你的需求和示例数据理清楚:
示例数据与逻辑说明
你的DataFrame子集如下(注释是核心逻辑):
| DATE | IN | 200D_MA | TEST | 逻辑说明 |
|---|---|---|---|---|
| 10/30/2013 | 0 | 1 | 0 | 初始未触发状态 |
| 10/31/2013 | 0 | 1 | 0 | 未满足触发条件 |
| 11/1/2013 | 1 | 1 | 1 | 触发条件:IN与200D_MA均为1,TEST设为1 |
| 11/4/2013 | 0 | 1 | 1 | 延续条件:上一行TEST为1且200D_MA为1 |
| 11/5/2013 | 0 | 1 | 1 | 延续条件同上 |
| 11/6/2013 | 0 | 1 | 1 | 保持激活状态 |
| 11/7/2013 | 0 | 1 | 1 | 保持激活状态 |
| 11/8/2013 | 0 | 1 | 1 | 保持激活状态 |
| 11/11/2013 | 0 | 0 | 0 | 终止条件:200D_MA为0,TEST重置为0 |
简单来说,就是触发后保持激活状态,直到终止条件出现。
两种实现方案
方案1:循环实现(直观易懂,适合小数据集)
这种方式和Excel公式的逻辑最接近,逐行判断状态:
import pandas as pd # 构造示例数据 data = { 'DATE': ['10/30/2013', '10/31/2013', '11/1/2013', '11/4/2013', '11/5/2013', '11/6/2013', '11/7/2013', '11/8/2013', '11/11/2013'], 'IN': [0, 0, 1, 0, 0, 0, 0, 0, 0], '200D_MA': [1, 1, 1, 1, 1, 1, 1, 1, 0], 'TEST': [0, 0, 1, 1, 1, 1, 1, 1, 0] } df = pd.DataFrame(data) df['DATE'] = pd.to_datetime(df['DATE']) # 初始化激活状态 active = False df['TEST_CALC'] = 0 # 逐行遍历更新状态 for idx, row in df.iterrows(): # 触发条件:IN和200D_MA同时为1 if row['IN'] == 1 and row['200D_MA'] == 1: active = True # 终止条件:200D_MA为0 elif row['200D_MA'] == 0: active = False # 赋值当前状态 df.loc[idx, 'TEST_CALC'] = 1 if active else 0 # 验证结果(TEST和TEST_CALC完全一致) print(df[['DATE', 'IN', '200D_MA', 'TEST', 'TEST_CALC']])
方案2:矢量化实现(高效快速,适合大数据集)
如果你的DataFrame行数很多,循环会很慢,用Pandas的矢量化操作效率会高得多:
import pandas as pd # 构造示例数据 data = { 'DATE': ['10/30/2013', '10/31/2013', '11/1/2013', '11/4/2013', '11/5/2013', '11/6/2013', '11/7/2013', '11/8/2013', '11/11/2013'], 'IN': [0, 0, 1, 0, 0, 0, 0, 0, 0], '200D_MA': [1, 1, 1, 1, 1, 1, 1, 1, 0], 'TEST': [0, 0, 1, 1, 1, 1, 1, 1, 0] } df = pd.DataFrame(data) df['DATE'] = pd.to_datetime(df['DATE']) # 1. 标记触发事件(1)和终止事件(-1) df['event'] = 0 df.loc[(df['IN'] == 1) & (df['200D_MA'] == 1), 'event'] = 1 df.loc[df['200D_MA'] == 0, 'event'] = -1 # 2. 累积求和,只要和>0就说明处于激活状态 df['TEST_CALC'] = (df['event'].cumsum() > 0).astype(int) # 验证结果 print(df[['DATE', 'IN', '200D_MA', 'TEST', 'TEST_CALC']])
这个方法的核心是用cumsum()追踪事件的累积效果:触发事件让累积和+1,终止事件让累积和-1,只要累积和大于0,就说明还在激活状态。
注意事项
- 如果数据中存在多个触发-终止周期,两种方案都能完美处理
- 矢量化方案的效率是循环的几十甚至上百倍,大数据集优先选择这个
内容的提问来源于stack exchange,提问作者J Westwood
相关产品推荐
相关产品推荐

