基于条件用Pandas去除重复行并新增prev_code列
问题描述
给定如下格式的CSV数据:
id | code | date -------------+----------------------------- | 1 | 2 | 2022-10-05 07:22:39+00::00 | | 1 | 0 | 2022-11-05 02:22:35+00::00 | | 2 | 3 | 2021-01-05 10:10:15+00::00 | | 2 | 0 | 2019-01-11 10:05:21+00::00 | | 2 | 1 | 2022-01-11 10:05:22+00::00 | | 3 | 2 | 2022-10-10 11:23:43+00::00 |
需要按以下规则处理数据:
- 去重
id行:优先保留code非0的记录;若同一id有多个非0code,选date最新的那条 - 新增
prev_code列,存储该id下未被选中的所有code值组成的列表
注:原示例中id=2的prev_code写为[0,2]是笔误,实际未被选中的code值为0和3,正确期望输出如下:
id | code | prev_code -------------+---------- | 1 | 2 | [0] | | 2 | 1 | [0,3] | | 3 | 2 | [] |
Pandas实现方案
import pandas as pd # 读取CSV数据,处理分隔符和多余空格 df = pd.read_csv('your_data.csv', sep='|', skipinitialspace=True) # 清理列名和单元格的多余空格 df.columns = df.columns.str.strip() df = df.apply(lambda x: x.str.strip() if x.dtype == 'object' else x) # 将date列转换为datetime类型,用于时间比较 df['date'] = pd.to_datetime(df['date'], errors='coerce') # 定义分组处理函数 def process_single_id(group): # 筛选当前id下code非0的记录 non_zero_records = group[group['code'] != 0] if not non_zero_records.empty: # 按时间降序排序,取最新的一条作为保留记录 main_record = non_zero_records.sort_values('date', ascending=False).iloc[0] else: # 兜底:如果所有code都是0,取任意一条(按需求场景可省略) main_record = group.iloc[0] # 收集未被选中的所有code值 excluded_codes = group[group.index != main_record.index]['code'].tolist() main_record['prev_code'] = excluded_codes return main_record # 按id分组处理,生成结果 result = df.groupby('id').apply(process_single_id).reset_index(drop=True) # 调整列顺序为目标格式 result = result[['id', 'code', 'prev_code']] # 输出结果 print(result)
代码说明
- 数据读取与清理:针对原CSV的
|分隔符和多余空格问题,用sep='|'和skipinitialspace=True读取,再统一清理列名和单元格的空格 - 时间类型转换:将
date列转为datetime类型,才能正确比较时间先后 - 分组处理逻辑:
- 对每个
id的分组,优先筛选非0code记录,按时间降序取最新的一条作为保留行 - 收集分组内除保留行外的所有
code值,存入prev_code列
- 对每个
- 结果整理:重置索引并调整列顺序,得到符合要求的输出格式
内容的提问来源于stack exchange,提问作者2shar
相关产品推荐
相关产品推荐

