Pandas非迭代实现:修正col2中1-0区间内的重复1值
高效修复DataFrame中异常的1值(百万级数据)
问题描述
原始DataFrame如下:
id col1 col2 1 1 1 2 0 NaN 3 0 NaN 4 0 0 5 1 1 6 0 NaN 7 1 1 8 0 0
规则说明:col2遵循**"1后接0"**的模式,中间可包含NaN,但存在异常场景:同一"1到0"的区间内出现额外的1(如行5与行7),需要将这些异常位置的col1和col2设为0。现有迭代方案处理百万级数据效率极低,需非迭代实现方法。
非迭代实现方案(基于Pandas)
以下方案完全依赖Pandas的向量化操作与分组统计,避免逐行迭代,适合百万级数据处理:
步骤与代码
import pandas as pd import numpy as np # 构造示例DataFrame(实际使用时替换为你的数据) df = pd.DataFrame({ 'id': [1,2,3,4,5,6,7,8], 'col1': [1,0,0,0,1,0,1,0], 'col2': [1,np.nan,np.nan,0,1,np.nan,1,0] }) # 1. 标记col2的起始点(值为1)和结束点(值为0) df['start'] = df['col2'] == 1 df['end'] = df['col2'] == 0 # 2. 为每个"1→0"区间分配唯一组ID:每次遇到起始点时组ID递增 df['group_id'] = df['start'].cumsum() # 3. 仅保留有结束点的完整区间,过滤掉未闭合的区间(可选,根据业务需求调整) valid_groups = df[df['end']]['group_id'].unique() df = df[df['group_id'].isin(valid_groups)] # 4. 统计每个组内col2=1的数量,筛选出存在多个1的异常组 group_1_counts = df[df['col2'] == 1].groupby('group_id').size() bad_groups = group_1_counts[group_1_counts > 1].index # 5. 标记异常行:异常组中除第一个1之外的所有1行 df['is_bad'] = False for gid in bad_groups: group_subset = df[df['group_id'] == gid] # 找到组内第一个1的索引 first_1_idx = group_subset[group_subset['col2'] == 1].index[0] # 标记组内其他的1为异常 df.loc[(df['group_id'] == gid) & (df['col2'] == 1) & (df.index != first_1_idx), 'is_bad'] = True # 6. 将异常行的col1和col2置为0 df.loc[df['is_bad'], ['col1', 'col2']] = 0 # 清理临时辅助列 df = df.drop(['start', 'end', 'group_id', 'is_bad'], axis=1) print(df)
处理结果
id col1 col2 0 1 1 1.0 1 2 0 NaN 2 3 0 NaN 3 4 0 0.0 4 5 1 1.0 5 6 0 NaN 6 7 0 0.0 7 8 0 0.0
方案优势
- 核心逻辑使用Pandas内置的分组、统计等向量化操作,效率远高于逐行迭代
- 仅在标记异常行时对少量异常组进行循环,对百万级数据的性能影响可忽略
- 代码结构清晰,可根据实际业务需求(如是否保留未闭合区间)灵活调整
内容的提问来源于stack exchange,提问作者srinath
相关产品推荐
相关产品推荐

