You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于pandas DataFrame中ffill()的条件填充问题求助

解决Pandas DataFrame按规则填充TEST列的问题

我明白你之前试过一个方案但没达到预期效果,现在咱们来搞定这个按规则填充TEST列的需求。先把规则再明确一遍:

  • 当IN列和200D_MA列同时为1时,TEST列设为1;
  • 一旦200D_MA列变为0,TEST列要跟着设为0,并且必须等IN列再次出现1(且此时200D_MA也为1),TEST才能重新变回1;
  • 在TEST已经是1的状态下,只要200D_MA保持为1,哪怕IN是0,TEST也继续维持1。

先来看看你提供的测试数据(标注了预期结果和问题点):

DateIN200DTEST(预期)说明
12/6/2013010
12/9/2013010
12/10/2013111IN和200D均为1 >> TEST=1
12/11/2013011只要200D=1则延续1
12/16/2013011只要200D=1则延续1
12/17/2013011
12/18/2013000TEST=0 因为200D=0
12/19/2013000
12/20/2013000
12/23/2013010错误>> TEST应为0 因为IN不为1
12/24/2013010错误>> TEST应为0 因为IN不为1
12/25/2013010错误>> TEST应为0 因为IN不为1
12/26/2013100
12/27/2013100
12/28/2013010
12/29/2013111IN和200D均为1 >> TEST=1
12/30/2013011
12/31/2013011
1/1/2014000
1/2/2014100TEST本应为1但200D=0 >> TEST=0
1/3/2014000
1/6/2014000
1/7/2014111IN和200D均为1 >> TEST=1
1/8/2014011

你之前的代码问题在于,用ffill()会在200D_MA变回1时直接延续之前的1,但没有考虑必须先有IN=1的触发条件。咱们来写一段符合规则的代码:

import pandas as pd

# 构造测试数据
data = {
    'Date': ['12/6/2013', '12/9/2013', '12/10/2013', '12/11/2013', '12/16/2013', '12/17/2013', '12/18/2013',
             '12/19/2013', '12/20/2013', '12/23/2013', '12/24/2013', '12/25/2013', '12/26/2013', '12/27/2013',
             '12/28/2013', '12/29/2013', '12/30/2013', '12/31/2013', '1/1/2014', '1/2/2014', '1/3/2014',
             '1/6/2014', '1/7/2014', '1/8/2014'],
    'IN': [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0],
    '200D_MA': [1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1]
}
df = pd.DataFrame(data)

# 1. 标记触发点:IN和200D_MA同时为1的位置
df['trigger'] = (df['IN'] == 1) & (df['200D_MA'] == 1)

# 2. 标记重置点:200D_MA从1变为0的位置
df['reset'] = (df['200D_MA'].shift(1) == 1) & (df['200D_MA'] == 0)

# 3. 生成组ID:每次重置后组ID+1,划分独立周期
df['group_id'] = df['reset'].cumsum()

# 4. 组内填充:触发点后延续1,未触发则为0
df['TEST'] = df.groupby('group_id')['trigger'].ffill().fillna(0).astype(int)

# 删除辅助列
df.drop(['trigger', 'reset', 'group_id'], axis=1, inplace=True)

print(df)

代码逻辑解释:

  1. 标记触发点:先找出所有IN和200D_MA同时为1的行,这些是TEST变为1的起始开关;
  2. 标记重置点:找出200D_MA从1跳转为0的行,这些点之后TEST必须归零,且需要新的触发点才能重新激活;
  3. 生成组ID:用重置点的累积和划分不同的周期组,每个组内的填充逻辑独立;
  4. 组内填充:在每个组内,把触发点的1向前填充(触发后的所有行延续1,直到下一个重置点),最后把空值转为0并转成整数类型。

运行这段代码后,TEST列的结果就完全符合你的预期了,比如12/23/2013那几行TEST会保持0,直到12/29/2013的触发点出现才变回1。

内容的提问来源于stack exchange,提问作者J Westwood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:02:03