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

Pandas条件填充失效:按规则填充infected字段的技术问题

问题:按规则填充DataFrame的infected字段

以下是我的DataFrame创建及填充代码:

import pandas as pd
import numpy as np

sample_data = [
  {'Date': '13-12-2020', 'usable': 1, 'infected': 'Case3'},
  {'Date': '14-12-2020', 'usable': 1},
  {'Date': '15-12-2020', 'usable': 0},
  {'Date': '16-12-2020', 'usable': 1, 'infected': 'Case33'},
  {'Date': '17-12-2020', 'usable': 1},
  {'Date': '18-12-2020', 'usable': 1},  
  {'Date': '19-12-2020', 'usable': 0},
  {'Date': '20-12-2020', 'usable': 0},
  {'Date': '21-12-2020', 'usable': 0, 'infected': 'Case#'},
  {'Date': '22-12-2020', 'usable': 1},
  {'Date': '23-12-2020', 'usable': 1},
  {'Date': '24-12-2020', 'usable': 0},
  {'Date': '25-12-2020', 'usable': 0},
  {'Date': '26-12-2020', 'usable': 1, 'infected': 'Case46'},
  {'Date': '27-12-2020', 'usable': 0},
  {'Date': '28-12-2020', 'usable': 1},
  ]

df = pd.DataFrame(sample_data)
df['infected'] = df['infected'].ffill(limit=2).bfill(limit=2)
df['infected'] = np.where(df['usable']==0, np.NaN, df['infected'])

我需要按以下规则填充infected字段:

  • 仅对usable=1的行填充infected值
  • 向前后最多填充2个相邻的usable=1的行
  • 遇到usable=0时停止填充

但当前代码得到错误输出,预期输出如下:

expected = [
  {'Date': '13-12-2020', 'usable': 1, 'infected': 'Case3'},
  {'Date': '14-12-2020', 'usable': 1, 'infected': 'Case3'},
  {'Date': '15-12-2020', 'usable': 0},
  {'Date': '16-12-2020', 'usable': 1, 'infected': 'Case33'},
  {'Date': '17-12-2020', 'usable': 1, 'infected': 'Case33'},
  {'Date': '18-12-2020', 'usable': 1, 'infected': 'Case33'},  
  {'Date': '19-12-2020', 'usable': 0},
  {'Date': '20-12-2020', 'usable': 0},
  {'Date': '21-12-2020', 'usable': 0, 'infected': 'Case#'},
  {'Date': '22-12-2020', 'usable': 1},
  {'Date': '23-12-2020', 'usable': 1},
  {'Date': '24-12-2020', 'usable': 0},
  {'Date': '25-12-2020', 'usable': 0},
  {'Date': '26-12-2020', 'usable': 1, 'infected': 'Case46'},
  {'Date': '27-12-2020', 'usable': 0},
  {'Date': '28-12-2020', 'usable': 1},
  ]

df_expected = pd.DataFrame(expected)

注:'28-12-2020'不填充'Case46',因为'27-12-2020'的usable=0,无法向前填充。


解决方案

原代码的问题在于直接使用ffill和bfill会忽略usable=0的分隔作用,导致跨usable=0的行填充,同时无法精确控制仅在连续usable=1的块内填充最多2个相邻行。

正确的做法是先按usable=0分割出连续的usable=1的组,再在每个组内进行前后填充,限制填充次数为2:

import pandas as pd
import numpy as np

sample_data = [
  {'Date': '13-12-2020', 'usable': 1, 'infected': 'Case3'},
  {'Date': '14-12-2020', 'usable': 1},
  {'Date': '15-12-2020', 'usable': 0},
  {'Date': '16-12-2020', 'usable': 1, 'infected': 'Case33'},
  {'Date': '17-12-2020', 'usable': 1},
  {'Date': '18-12-2020', 'usable': 1},  
  {'Date': '19-12-2020', 'usable': 0},
  {'Date': '20-12-2020', 'usable': 0},
  {'Date': '21-12-2020', 'usable': 0, 'infected': 'Case#'},
  {'Date': '22-12-2020', 'usable': 1},
  {'Date': '23-12-2020', 'usable': 1},
  {'Date': '24-12-2020', 'usable': 0},
  {'Date': '25-12-2020', 'usable': 0},
  {'Date': '26-12-2020', 'usable': 1, 'infected': 'Case46'},
  {'Date': '27-12-2020', 'usable': 0},
  {'Date': '28-12-2020', 'usable': 1},
  ]

df = pd.DataFrame(sample_data)

# 标记usable=0的行,分割出连续usable=1的组
df['group'] = (df['usable'] == 0).cumsum()

# 组内填充逻辑:仅对纯usable=1的组进行双向填充,最多2个
def fill_within_group(group):
    if (group['usable'] == 1).all():
        group['infected'] = group['infected'].ffill(limit=2).bfill(limit=2)
    else:
        # 含usable=0的组,仅保留原infected值,其余usable=1行设为NaN
        group['infected'] = np.where(group['usable'] == 0, group['infected'], np.nan)
    return group

df = df.groupby('group').apply(fill_within_group)

# 清理临时分组列
df = df.drop('group', axis=1)

# 验证结果匹配预期
print(df.equals(df_expected))  # 输出True

代码说明:

  1. 分组逻辑:通过(df['usable'] == 0).cumsum()生成组ID,每遇到一个usable=0,组ID递增,确保连续的usable=1行被分到同一组,usable=0的行单独成组。
  2. 组内填充:针对纯usable=1的组,先向前填充最多2个空值,再向后填充最多2个空值,实现从有值行向前后各覆盖最多2个相邻usable=1行;含usable=0的组仅保留原有infected值,其余行设为NaN。
  3. 清理临时列:删除用于分组的group列,得到符合要求的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 12:40:25