基于ID的多掩码过滤:筛选DataFrame中符合对应日期范围的行
批量过滤DataFrame中符合ID对应日期范围的行
现有数据
原始DataFrame df
包含id(非唯一,取值1-3)和date(datetime类型)两列,数据如下:
id, date 1, 2020-5-11 1, 2019-3-2 2, 2018-7-29 3, 2017-2-21 3, 2017-2-23
ID对应起止日期表
存储每个id的允许日期范围(注:原数据中2020-2-31为无效日期,已修正为2020-2-29):
id, startdate, enddate 1, 2015-1-1, 2020-1-1 2, 2019-2-1, 2020-2-29 3, 2017-2-1, 2020-2-29
需求
过滤df,排除所有id对应的date不在上述起止日期范围内的行。当前仅能逐个id循环处理,无法批量实现,现有循环代码:
for each, startdate, enddate in ids: mask = (df['date'].dt.date >= startdate) & (df['date'].dt.date <= enddate) df[df['id']==each].loc[mask]
期望输出
保留符合条件的行,结果如下:
id, date 1, 2019-3-2 3, 2017-2-21 3, 2017-2-23
批量处理方案
用Pandas的合并+条件过滤实现高效批量处理,无需循环:
完整代码
import pandas as pd # 1. 初始化原始DataFrame df df = pd.DataFrame({ 'id': [1,1,2,3,3], 'date': pd.to_datetime(['2020-5-11', '2019-3-2', '2018-7-29', '2017-2-21', '2017-2-23']) }) # 2. 初始化起止日期DataFrame df_range df_range = pd.DataFrame({ 'id': [1,2,3], 'startdate': pd.to_datetime(['2015-1-1', '2019-2-1', '2017-2-1']), 'enddate': pd.to_datetime(['2020-1-1', '2020-2-29', '2020-2-29']) }) # 3. 按id合并两个DataFrame,匹配对应id的起止日期 merged_df = pd.merge(df, df_range, on='id', how='left') # 4. 过滤date在[startdate, enddate]区间内的行 filtered_df = merged_df[(merged_df['date'] >= merged_df['startdate']) & (merged_df['date'] <= merged_df['enddate'])] # 5. 保留原DataFrame需要的列 result_df = filtered_df[['id', 'date']] # 输出结果 print(result_df)
代码说明
- 通过
merge按id关联两个表,让每一行数据都能获取到对应id的起止日期 - 用Pandas原生向量式条件过滤,比循环处理效率高得多
- 最后保留原数据所需的
id和date列,得到目标结果
运行结果
id date 1 1 2019-03-02 3 3 2017-02-21 4 3 2017-02-23
内容的提问来源于stack exchange,提问作者NotLost
相关产品推荐
相关产品推荐

