如何用Python实现DataFrame滚动求和并标记抵消组?
解决方案
原代码问题分析
你的代码存在以下关键问题,导致无法得到预期结果:
- 仅标记了滚动窗口的最后一行,没有将窗口内的所有行标记为
Canceled - 只处理了固定5行的窗口,未覆盖需求中的2-4行窗口
- 缺少组编号和组内行号的生成逻辑
完整实现代码
以下是满足需求的完整代码,包含数据预处理、滚动窗口标记、组编号与行号生成:
# 1. 数据预处理(保留你的原有筛选逻辑) df_sorted = df.sort_values('No Piece FI') df_sorted['No Piece FI'] = df_sorted['No Piece FI'].astype(str) df = df_sorted[df_sorted['No Piece FI'].str.startswith('11')].reset_index(drop=True) # 2. 初始化标记列 df['Annulé'] = '' # 3. 遍历2-5行的所有窗口大小,标记和为0的窗口内所有行 for window_size in range(2, 6): # 计算指定窗口大小的滚动和(min_periods=window_size确保窗口是满员的N行) rolling_sums = df['CP'].rolling(window=window_size, min_periods=window_size).sum() # 找到所有和为0的窗口的结束索引 zero_window_end_indices = rolling_sums[rolling_sums == 0].index # 标记每个窗口内的全部行 for end_idx in zero_window_end_indices: start_idx = end_idx - window_size + 1 df.loc[start_idx:end_idx, 'Annulé'] = 'Canceled' # 4. 生成组编号:连续的相同标记状态为一组 df['Group'] = (df['Annulé'] != df['Annulé'].shift()).cumsum() # 5. 生成组内行号 df['Lines'] = df.groupby('Group').cumcount() + 1 # (可选)调整列顺序匹配预期输出 df = df[['Lines', 'CP', 'Annulé', 'Group']]
代码说明
- 重置索引:避免原DataFrame索引不连续导致窗口切片错误
- 多窗口遍历:依次处理2/3/4/5行的窗口,确保覆盖所有需求中的窗口大小
- 全窗口标记:找到和为0的窗口结束索引后,通过切片标记该窗口内的所有行
- 组编号生成:通过对比当前行与上一行的
Annulé状态,将连续的相同状态划分为同一组 - 组内行号:用
groupby.cumcount()生成每组内的递增行号
特殊情况调整
如果你的需求是「窗口最大5行,最少2行(即包含2-5行的任意滚动窗口)」,而非固定窗口大小,可以修改滚动求和逻辑:
window_max = 5 # 计算最大5行、最少2行的滚动和 rolling_sums = df['CP'].rolling(window=window_max, min_periods=2).sum() # 标记所有和为0的窗口内的行 for idx in rolling_sums[rolling_sums == 0].index: start_idx = max(0, idx - window_max + 1) df.loc[start_idx:idx, 'Annulé'] = 'Canceled'
内容的提问来源于stack exchange,提问作者Teddy
相关产品推荐
相关产品推荐

