基于滚动时间窗口的Pandas值重现检测问题求助
解决按分组时间窗口检查值前后出现的问题
我来帮你搞定这个需求!先明确一下我们要实现的目标:按ColN字段分组,针对每一行,检查它的ColN_ext值是否在当前日期前后5天的滚动窗口内的其他行中出现(区分前后),最终生成符合预期的flag列。
首先,先把你提供的初始DataFrame代码放出来,方便我们复现环境:
import pandas as pd import numpy as np df = pd.DataFrame() df['ColN']=['AAA', 'AAA', 'AAA', 'AAA', 'ABC'] df['ColN_dt']=['03-01-2018', '03-04-2018', '03-05-2018', '03-08-2018', '03-12-2018'] df['ColN_ext']=['A', 'B', 'B', 'B', 'B'] df['ColN_dt'] = pd.to_datetime(df['ColN_dt'])
需求拆解
先对应预期的flag结果[NaN, 0, 1, NaN, NaN]拆解规则:
- 第1行(AAA组,2018-03-01,ext=A):窗口内只有后续行,且没有A,保持NaN;
- 第2行(AAA组,2018-03-04,ext=B):窗口内后续有B,但前序没有,所以flag=0;
- 第3行(AAA组,2018-03-05,ext=B):窗口内前序和后续都有B,所以flag=1;
- 第4行(AAA组,2018-03-08,ext=B):窗口内只有前序有B,后续无数据,保持NaN;
- 第5行(ABC组,仅一行):窗口内无其他行,保持NaN。
解决方案代码
下面是实现这个逻辑的代码,注释已经写得很清楚了:
# 先按ColN分组,确保每个组内按日期排序(原数据已经有序,但加这一步更稳妥) df = df.sort_values(['ColN', 'ColN_dt']).reset_index(drop=True) def check_ext_in_window(group): # 初始化flag列为NaN group['flag'] = np.nan total_rows = len(group) for idx in range(total_rows): current_ext = group['ColN_ext'].iloc[idx] current_date = group['ColN_dt'].iloc[idx] # 计算窗口的时间范围:当前日期前后5天 window_start = current_date - pd.Timedelta(days=5) window_end = current_date + pd.Timedelta(days=5) # 筛选窗口内除当前行外的所有数据 window_data = group[ (group['ColN_dt'] >= window_start) & (group['ColN_dt'] <= window_end) & (group.index != idx) ] # 窗口内没有其他数据,直接跳过 if len(window_data) == 0: continue # 检查当前ext是否在窗口内的前序行(日期早于当前)存在 has_before = any(window_data[window_data['ColN_dt'] < current_date]['ColN_ext'] == current_ext) # 检查当前ext是否在窗口内的后序行(日期晚于当前)存在 has_after = any(window_data[window_data['ColN_dt'] > current_date]['ColN_ext'] == current_ext) # 根据检查结果设置flag值 if has_before and has_after: group['flag'].iloc[idx] = 1 elif has_before or has_after: group['flag'].iloc[idx] = 0 return group # 把函数应用到每个分组 df = df.groupby('ColN', group_keys=False).apply(check_ext_in_window) # 查看结果 print(df['flag'].tolist()) # 输出:[nan, 0.0, 1.0, nan, nan]
代码说明
- 排序分组:确保每个组内的数据是按日期顺序排列的,避免窗口计算出错;
- 窗口范围计算:用
pd.Timedelta来定义前后5天的时间窗口,比固定行数的滚动窗口更贴合你的需求(因为日期可能不连续); - 前后存在性检查:分别判断当前
ColN_ext在窗口内的前序和后序行中是否存在,再根据组合结果设置flag; - 边界处理:如果窗口内没有其他数据,保持flag为NaN,符合预期。
如果你的数据集很大,遍历的方式可能效率不够高,可以考虑预计算每个组的ColN_ext和日期的映射关系来优化,但对于一般规模的数据,这个方法已经足够清晰好用了。
内容的提问来源于stack exchange,提问作者Nee
相关产品推荐
相关产品推荐

