Pandas按同一ID对DataFrame执行多条件状态修改求助
解决方案
首先确保日期列是可比较的datetime类型,再通过分组提取基准日期,最后组合条件修改Status:
步骤1:准备数据并转换日期类型
import pandas as pd # 构造示例数据 data = { 'ID': [42872, 42872, 42872, 9999], 'user': ['luaquint@a.com.co', 'andres@a.com.co', 'luaquint@a.com.co', 'luaquint@a.com.co'], 'reception_date': ['2022-03-30', '2022-03-01', '2022-03-07', '2022-03-07'], 'end_date': ['2022-03-30', '2022-03-04', '2022-03-30', '2022-03-30'], 'Status': ['Accepted', 'Returned', 'In Study', 'Rejected'] } df = pd.DataFrame(data) # 转换end_date为datetime类型(字符串无法直接比较大小) df['end_date'] = pd.to_datetime(df['end_date'])
步骤2:提取每个ID的Accepted记录基准日期
# 按ID分组,获取每个组中Status为Accepted的最大end_date(兼容多Accepted记录场景) accepted_end = df[df['Status'] == 'Accepted'].groupby('ID')['end_date'].max().rename('accepted_end') # 将基准日期合并到原表,每个ID的所有行都能拿到对应的判断值 df = df.merge(accepted_end, on='ID', how='left')
步骤3:组合条件修改Status
# 构建筛选条件: # 1. 当前ID存在Accepted记录(accepted_end不为空) # 2. 当前记录Status是"In Study" # 3. Accepted记录的end_date >= 当前记录的end_date condition = (df['accepted_end'].notna()) & (df['Status'] == 'In Study') & (df['accepted_end'] >= df['end_date']) # 对符合条件的行修改Status df.loc[condition, 'Status'] = 'Accepted' # 移除辅助列 df = df.drop('accepted_end', axis=1)
最终输出
ID user reception_date end_date Status 0 42872 luaquint@a.com.co 2022-03-30 2022-03-30 Accepted 1 42872 andres@a.com.co 2022-03-01 2022-03-04 Returned 2 42872 luaquint@a.com.co 2022-03-07 2022-03-30 Accepted 3 9999 luaquint@a.com.co 2022-03-07 2022-03-30 Rejected
关键说明
- 必须转换日期类型:字符串格式的日期无法直接做大小比较,这是新手容易踩的坑。
- 分组+merge比
apply更高效:apply逐行处理在数据量大时速度慢,分组提取基准值再合并属于Pandas矢量化操作,性能更优。 - 兼容多Accepted记录:如果一个ID有多个Accepted记录,取最大的end_date作为判断基准,保证逻辑严谨性。
内容的提问来源于stack exchange,提问作者Andrés HK
相关产品推荐
相关产品推荐

